Unexpected ClassnotFoundException on reflective Class#getMethod
Sanne Grinovero
sgrinove at redhat.com
Thu Mar 31 10:20:15 UTC 2016
Thanks Alex,
that clarifies a lot, I was just about to try with a different dependency.
So this is not a reflection bug, but I'm just realising now that has
quite significant impact on JavaEE:
the Synchronization type is defined as public API of the specification [1].
Changing the JavaEE API isn't going to be very popular, so I guess the
expectation is for
containers to regularly override the modules?
This won't affect just the regular EE application servers, as these
APIs are often used also
in standalone JavaSE applications, as many components of the JavaEE spec can
be run in "standalone" or "embedded" modes.
For example Hibernate will now have to require the application launcher to apply
customizations to the JVM boot parameters, and probably so any other JPA
implementation.
1 - http://docs.oracle.com/javaee/7/api/javax/transaction/Synchronization.html
Thanks,
Sanne
On Wed, Mar 30, 2016 at 11:07 PM, Alex Buckley <alex.buckley at oracle.com> wrote:
> The JDK 9b111 runtime image includes the java.transaction module which
> exports the javax.transaction package. The application class loader will try
> to load javax.transaction.* types from there, not from a JAR on the
> classpath. As you probably guess, the JDK's java.transaction module does not
> contain the javax.transaction.Synchronization type.
>
> You can either supply an alternate java.transaction module to override the
> one in the JDK (-upgrademodulepath), or you can inject your additional
> classes directly into the module in the JDK (-Xpatch). Please see JEP 261.
>
> Alex
>
>
> On 3/30/2016 2:39 PM, Sanne Grinovero wrote:
>>
>> Hello all,
>> looks like I've found an issue on invoking Class#getMethod.
>>
>> This method is used by Maven when scanning the project's classpath to
>> identify JUnit tests - which it does by default on any Maven project -
>> so I'm afraid the impact could be quite large.
>>
>> I've been able to narrow it down to this small test which doesn't need
>> neither Maven nor JUnit, however to reproduce the issue the project
>> must have a dependency to some third party jar.
>> In this reproducer I'm using javax.transaction.Synchronization, a copy
>> can be obtained from:
>> -
>> https://repository.jboss.org/nexus/service/local/repositories/central/content/org/jboss/spec/javax/transaction/jboss-transaction-api_1.2_spec/1.0.0.Final/jboss-transaction-api_1.2_spec-1.0.0.Final.jar
>>
>>
>> ==== Main.java ====
>> public class Main {
>>
>> public static void main(String[] args) {
>> Class clazz = SecondClass.class;
>> try {
>> clazz.getMethod("notexisting", new Class[0]);
>> } catch (NoSuchMethodException e) {
>> e.printStackTrace();
>> }
>> System.out.println("All good");
>> }
>>
>> }
>> ==== SecondClass.java ====
>> import javax.transaction.Synchronization;
>>
>> public class SecondClass {
>>
>> public void registerSynchronization(Synchronization synchronization) {
>> }
>>
>> }
>> ==== EOF ====
>>
>>
>> On Java8 or Java9 build 9-ea+110 the output is, as expected:
>>
>>> java.lang.NoSuchMethodException: SecondClass.notexisting()
>>> at java.lang.Class.getMethod(Class.java:1786)
>>> at Main.main(Main.java:6)
>>> All good
>>
>>
>>
>> On Java9 build 9-ea+111 though I'll have this:
>>
>>> Exception in thread "main" java.lang.NoClassDefFoundError:
>>> javax/transaction/Synchronization
>>> at java.lang.Class.getDeclaredMethods0(java.base at 9-ea/Native Method)
>>> at
>>> java.lang.Class.privateGetDeclaredMethods(java.base at 9-ea/Class.java:2937)
>>> at
>>> java.lang.Class.privateGetMethodRecursive(java.base at 9-ea/Class.java:3282)
>>> at java.lang.Class.getMethod0(java.base at 9-ea/Class.java:3252)
>>> at java.lang.Class.getMethod(java.base at 9-ea/Class.java:1961)
>>> at Main.main(Main.java:6)
>>> Caused by: java.lang.ClassNotFoundException:
>>> javax.transaction.Synchronization
>>> at
>>> jdk.internal.loader.BuiltinClassLoader.loadClass(java.base at 9-ea/BuiltinClassLoader.java:368)
>>> at
>>> jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(java.base at 9-ea/ClassLoaders.java:185)
>>> at java.lang.ClassLoader.loadClass(java.base at 9-ea/ClassLoader.java:419)
>>> ... 6 more
>>
>>
>> I hope I have sent this to the right mailing list.
>> I've reported the same issue on bugreport.java.com, but the only ID I
>> have about that report is the "Review ID": JI-9033943
>> The reproducer in this email is much better than in the other report,
>> I can't check what I sent but I believe I might have sent an outdated
>> version; apologies for any confusion.
>>
>> Thanks,
>> Sanne Grinovero
>>
>
More information about the jigsaw-dev
mailing list