OiO.lk Blog java ClassNotFoundException when trying to reference classes in jars in a sub-directory inside the executable jar
java

ClassNotFoundException when trying to reference classes in jars in a sub-directory inside the executable jar


Projects

I have 2 Gradle based Java projects which both get packaged as .jar files:

  1. Core

    • A java-library
    • Creates a .jar containing the projects .class files and a lib/ inside the .jar containing all the project’s 3rd party dependency .jar files
    • Contains the following in it’s build script for the .jar that is created for the project.
tasks.getByName<Jar>("jar") {
    enabled = true
    archiveClassifier.value("api")

    from(sourceSets.main.get().output)
    into("lib") {
        from(configurations.runtimeClasspath)
    }
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
  1. Import

    • Will be executed on command line
    • Creates a .jar containing the projects .class files and inside lib/ is the project’s 3rd party dependency .jar files (Same as the ones packaged inside core.jar://lib/*.jar) i.e import.jar://lib/*.jar
    • Contains the following in it’s build script for the .jar that is created for the project

Import pulls in a dependency of Core in it’s build script using:

dependencies {

    implementation group: 'com.company.core', name: 'core', version: '0.1.0-SNAPSHOT', classifier: 'api'

This is the jar task definition for Import:

jar {
    zip64 = true
    manifest {
        attributes 'Main-Class': 'com.import.Runner'
    }
    from {
        duplicatesStrategy(DuplicatesStrategy.INCLUDE)

        configurations.runtimeClasspath.collect {

            if (it.isDirectory()) {
                println "Directory: $it" // Never printed
                it
            } else {
                println "Zip Tree: $it" // Printed, contains paths to jars from my maven directory on my file system
                zipTree(it)
            }
        }
    }

    exclude 'META-INF/*.RSA', 'META-INF/*.SF', 'META-INF/*.DSA'
}

Execution

When I execute Import’s jar using this:

java -cp import.jar com.import.Runner

// Also tried:
java -cp "import.jar:lib/*" com.import.Runner

I end up with NoClassDefFoundError exceptions:

Exception in thread "main" java.lang.NoClassDefFoundError: com/company/exception/ApplicationException
    at com.import.ImportClient.<init>(ImportClient.java:24)
Caused by: java.lang.ClassNotFoundException: com.company.exception.ApplicationException

It appears the executable isn’t able to find the .class files inside the 3rd party jars that are inside the lib/ directory of import.jar.

Shouldn’t the JVM be able to load the .class files from the .jar files inside my executable jar?

Considering I updated the classpath flag to contain -cp "import.jar:lib/*"? does that not apply to inside the jar?



You need to sign in to view this answers

Exit mobile version