janino-compiler/janino

commons-compiler-jdk: Unable to load class

lglauer opened this issue · 12 comments

Hello!

When only commons-compiler-jdk is on the classpath, but not janino the SimpleCompiler class from commons-compiler-jdk is used. Since release 3.17 it fails to load the annotation class javax.annotation.Nonnull from the classpath. Prior this scenario worked fine, so it seems to be a regression. I created a minimal reproducible example for this case: https://github.com/lglauer/janino-test

When executed it prints the following exception:

Exception in thread "main" org.codehaus.commons.compiler.CompileException: File 'simplecompiler', Line 2, Column 24: package javax.annotation does not exist (compiler.err.doesnt.exist)
	at org.codehaus.commons.compiler.jdk.Compiler$1.report(Compiler.java:329)
	at jdk.compiler/com.sun.tools.javac.api.ClientCodeWrapper$WrappedDiagnosticListener.report(ClientCodeWrapper.java:736)
	at jdk.compiler/com.sun.tools.javac.util.Log.writeDiagnostic(Log.java:734)
	at jdk.compiler/com.sun.tools.javac.util.Log$DefaultDiagnosticHandler.report(Log.java:718)
	at jdk.compiler/com.sun.tools.javac.util.Log.report(Log.java:678)
	at jdk.compiler/com.sun.tools.javac.comp.Resolve.logResolveError(Resolve.java:3714)
	at jdk.compiler/com.sun.tools.javac.comp.Resolve.accessInternal(Resolve.java:2475)
	at jdk.compiler/com.sun.tools.javac.comp.Resolve.accessBase(Resolve.java:2518)
	at jdk.compiler/com.sun.tools.javac.comp.Attr.selectSym(Attr.java:3717)
	at jdk.compiler/com.sun.tools.javac.comp.Attr.visitSelect(Attr.java:3603)
	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCFieldAccess.accept(JCTree.java:2130)
	at jdk.compiler/com.sun.tools.javac.comp.Attr.attribTree(Attr.java:655)
	at jdk.compiler/com.sun.tools.javac.comp.Attr.attribType(Attr.java:715)
	at jdk.compiler/com.sun.tools.javac.comp.Attr.attribType(Attr.java:708)
	at jdk.compiler/com.sun.tools.javac.comp.TypeEnter$ImportsPhase.attribImportType(TypeEnter.java:441)
	at jdk.compiler/com.sun.tools.javac.comp.TypeEnter$ImportsPhase.doImport(TypeEnter.java:424)
	at jdk.compiler/com.sun.tools.javac.comp.TypeEnter$ImportsPhase.resolveImports(TypeEnter.java:364)
	at jdk.compiler/com.sun.tools.javac.comp.TypeEnter$ImportsPhase.runPhase(TypeEnter.java:321)
	at jdk.compiler/com.sun.tools.javac.comp.TypeEnter$Phase.doCompleteEnvs(TypeEnter.java:282)
	at jdk.compiler/com.sun.tools.javac.comp.TypeEnter$Phase.completeEnvs(TypeEnter.java:251)
	at jdk.compiler/com.sun.tools.javac.comp.TypeEnter.complete(TypeEnter.java:198)
	at jdk.compiler/com.sun.tools.javac.code.Symbol.complete(Symbol.java:642)
	at jdk.compiler/com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:1326)
	at jdk.compiler/com.sun.tools.javac.comp.Enter.complete(Enter.java:583)
	at jdk.compiler/com.sun.tools.javac.comp.Enter.main(Enter.java:560)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.enterTrees(JavaCompiler.java:1066)
	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:937)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:147)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:100)
	at jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:94)
	at org.codehaus.commons.compiler.jdk.Compiler.compile(Compiler.java:359)
	at org.codehaus.commons.compiler.jdk.Compiler.compile(Compiler.java:209)
	at org.codehaus.commons.compiler.jdk.Compiler.compile(Compiler.java:157)
	at org.codehaus.commons.compiler.jdk.SimpleCompiler.cook(SimpleCompiler.java:161)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:82)
	at org.codehaus.commons.compiler.Cookable.cook(Cookable.java:77)
	at main.Main.getClazz(Main.java:24)
	at main.Main.main(Main.java:43)

If janino is added as a dependency or if commons-compiler-jdk 3.16 is used the example code works fine and prints "Hello World!".

Thanks in advance!

we have run into a similar issue. in our case janino, commons-compiler and commons-compiler-jdk are all on the classpath. compilation fail when importing a class from a dependency.

the exact same code runs as is with 3.1.6. the only change being the dependency bump to 3.1.7.

it should be noted that the problem only manifest itself when using the jdk compiler (org.codehaus.commons.compiler.jdk.CompilerFactory). the janino compiler (org.codehaus.janino.CompilerFactory) works just fine.

@aunkrig Any comment? Is janino still actively maintained? This is a serious regression and should be fixed ASAP.

I'll look into it soon.

The answer is very simple: Both "commons-compiler-jdk" and "janino" say "class javax.annotation.Nonnull not found" because -- that class cannot be found!
The reason being is that the annotation interface "javax.annotation.Nonnull" is not part of the JRE (tested with 8, 11 and 17), so one needs an extra library that supplies this annotation interface. If found the following libs:

com.google.code.findbugs:jsr305-3.0.2
org.apache.tools.ant:annotations-2.0.1

In other words: When you switched from 3.1.6 to 3.1.7, you must have accidentially removed that library from the classpath!

@aunkrig Did you have a look at the minimal reproducible example? It has a dependency to com.google.code.findbugs:jsr305 (see here). And as I said it works with commons-compiler-jdk:3.16 and fails with commons-compiler-jdk:3.17, no other difference.

Oops, I missed that dependency when I ran the sample program. Now I can reproduce the problem... stay tuned.

I think I fixed it (JavaFileManagers.java:120)... please test!

I also added a regression test case "testIssue168()" that verifies the absence of the bug.

Thank you! I will test it in the next days.

@aunkrig the fix is working for my test case. can you also please include PR #170 ?

Yes, that solution seems to work! Thanks 👍

My pleasure! Thank you for the very useful test case. I added a regression test case org.codehaus.commons.compiler.tests.ReportedBugsTest.testIssue168() that verifies this fix.