# Accessing the runtime classloader from the gradle build script

**URL:** <https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131>\
**Category:** Help/Discuss\
**Created:** [March 12, 2016, 10:13am UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131 "2016-03-12T10:13:05Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![milanov](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/milanov/32/4455_2.png) [@milanov](https://discuss.gradle.org/u/milanov)\
**Post date:** [March 12, 2016, 10:13am UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/1 "2016-03-12T10:13:05Z")

</div>

I’m trying to use a code generation library from my Gradle build script, but i’m facing an error - I don’t seem to be able to access my own classes from the build file. The task I have is the following:

```groovy
    def exporter = new GenericExporter();
    exporter.setTargetFolder(sourceSets.generated.java.srcDirs.first());
    exporter.export("com.company.project");

```

The default `GenericExporter` constructor is instantiated with a `Thread.currentThread().getContextClassLoader()` class loader. When I run the task, I get nothing, meaning no classes that are in the `com.company.project` are found.  
When I have the same code in my `Application` class (the main class inside my project), the code generation works. I debugged and saw that when executing the task from the gradle file I don’t have access to my own `com.company.project` classes.

Moreover, the project has a multi-project setup. The code generation task I’ve added to `subprojects`. Moreover I researched and tried to also add the following inside `subprojects`, but it didn’t help:

```groovy
    buildscript {
        dependencies {
            classpath files("${buildDir}/classes")
        }
    } 

```

Any suggestions would be greatly appreciated.

---

<div class="post-metadata">

**Author:** ![mark\_vieira](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/mark_vieira/32/5396_2.png) [@mark\_vieira](https://discuss.gradle.org/u/mark_vieira)\
**Post date:** [March 12, 2016, 4:20pm UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/2 "2016-03-12T16:20:37Z")

</div>

This is the problem in that the build script cannot depend on code that is compiled by the build script. There is a cyclic dependency here. You have a couple of options.

1. Put the code needed by the build in the [buildSrc](https://docs.gradle.org/current/userguide/organizing_build_logic.html#sec:build_sources) project
2. Publish the code needed by the build and depend on it as an external dependency

---

<div class="post-metadata">

**Author:** ![milanov](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/milanov/32/4455_2.png) [@milanov](https://discuss.gradle.org/u/milanov)\
**Post date:** [March 13, 2016, 11:07pm UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/3 "2016-03-13T23:07:43Z")

</div>

Hi, I read about that problem but seem to not be able to grasp it completely. Wouldn’t having a task that first compiles only the model classes and then one that generates other files from the already compiled models be sufficient?  
I’m saying that because both of your solutions seem to suggest kind of major changes - either a buildSrc project that contains the current top level project with all subproject or 2) (again having a dependency on the whole project). I’m looking for a simple solution that would involve minimum changes to the current build setup.

---

<div class="post-metadata">

**Author:** ![st\_oehme](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/st_oehme/32/5249_2.png) [@st\_oehme](https://discuss.gradle.org/u/st_oehme)\
**Post date:** [March 14, 2016, 2:01pm UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/4 "2016-03-14T14:01:35Z")

</div>

I think you and Mark misunderstood each other. You don’t want to use the compiled classes _in_ the buildscript. You want to postprocess them in another task. That’s an important difference.

> [@milanov](#):
>
> The default GenericExporter constructor is instantiated with a Thread.currentThread().getContextClassLoader() class loader.

That sounds too inflexible, the exporter should take a `ClassLoader` argument.

> [@milanov](#):
>
> When I run the task, I get nothing, meaning no classes that are in the com.company.project are found.

Of course, the buildscript is compiled and instantiated _before_ your build can start, so your production code cannot be in the same classloader.

If you want to load your production classes for further processing, you can use a URLClassLoader. You might want to change your exporter to use a more efficient library like ASM though. That’s much faster.

---

<div class="post-metadata">

**Author:** ![milanov](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/milanov/32/4455_2.png) [@milanov](https://discuss.gradle.org/u/milanov)\
**Post date:** [March 14, 2016, 4:14pm UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/5 "2016-03-14T16:14:58Z")

</div>

I assumed there might be some misunderstanding, but I couldn’t express myself more clearly.

> [@st\_oehme](#):
>
> the exporter should take a ClassLoader argument

Yes, it does in fact does take a class loader as argument.

> [@st\_oehme](#):
>
> You might want to change your exporter to use a more efficient library like ASM though

The exporter is not mine to change, it’s part of the QueryDSL library.

> [@st\_oehme](#):
>
> If you want to load your production classes for further processing, you can use a URLClassLoader

I tried to do so, but again with no result. Maybe this is a good time to mention that the files I’m trying to process are `Groovy` ones. Nevertheless, I tried to instantiate the class loader by two different ways, as shown below, but printing the loaded classes inside of both reveals not a single “com.company.project” class (only the jars of some external libraries I depend on).

```
def classLoader = new URLClassLoader(sourceSets.main.compileClasspath.collect { it.toURI().toURL() } as URL[])
def classLoader = new URLClassLoader(configurations.runtime.collect { it.toURI().toURL() } as URL[])

```

---

<div class="post-metadata">

**Author:** ![st\_oehme](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/st_oehme/32/5249_2.png) [@st\_oehme](https://discuss.gradle.org/u/st_oehme)\
**Post date:** [March 14, 2016, 6:44pm UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/6 "2016-03-14T18:44:07Z")

</div>

You want `sourceSets.main.runtimeClasspath`.

`sourceSets.main.compileClasspath` only contains what is necessary to compile the code (and of course the code can’t depend on itself to compile 🙂 )

`configurations.runtime` will only give you the runtime dependencies of your code.

---

<div class="post-metadata">

**Author:** ![milanov](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/milanov/32/4455_2.png) [@milanov](https://discuss.gradle.org/u/milanov)\
**Post date:** [March 16, 2016, 12:15pm UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/7 "2016-03-16T12:15:13Z")

</div>

Thank you, it’s currently working with the `sourceSets.main.runtimeClasspath`. The problem I had before when I tried to use the `runtimeClasspath` was that I received an error saying that I `cannot change dependencies of configuration ':app:runtime' after it has been resolved`.

My root project’s build.gradle looks like:

```gradle
build script { }
subprojects {}
project('1') {}
project('2') {}
...
project('n') {
    apply plugin: 'war'

    dependencies {
       compile project('1')
       ...

       providedRuntime('xxx')
    }
}

```

I “fixed” this by adding my generation task in another `subproject` section below the last project definition, i.e. after `project('n')`. This works, but 1) looks a bit strange and it would be great to have the previous structure and 2) it seems to be executed on every other task that I execute, i.e. `compileGroovy`, `clean`, etc.  
Again, thanks for the very useful responses 🙂

---

<div class="post-metadata">

**Author:** ![st\_oehme](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/st_oehme/32/5249_2.png) [@st\_oehme](https://discuss.gradle.org/u/st_oehme)\
**Post date:** [March 16, 2016, 1:26pm UTC](https://discuss.gradle.org/t/accessing-the-runtime-classloader-from-the-gradle-build-script/15131/8 "2016-03-16T13:26:43Z")

</div>

> [@milanov](#):
>
> when I tried to use the runtimeClasspath was that I received an error

You should only be instantiating the URLClassLoader inside the task action, not in the configuration phase. Otherwise, you are resolving dependencies too early.

Simplified:

Don’t:

```gradle
task postProcess() {
  def loader = newUrlClassLoader()
}

```

Do:

```gradle
taks postProcess() {
  doLast {
    def loader = new UrlClassLoader()
  }
}

```
