spring-loaded
spring-loaded copied to clipboard
NoSuchMethodException is thrown by ReflectiveInterceptor.jlClassGetDeclaredConstructor which changes jdk code behavior
-- Test Case -- [oracle@c7 ~]$ wget https://github.com/spring-projects/spring-loaded/archive/refs/heads/master.zip [oracle@c7 ~]$ unzip -qo master.zip [oracle@c7 ~]$ cd spring-loaded-master/ [oracle@c7 spring-loaded-master]$ ./gradlew build -x test
You may see error, hang @ <===----------> 30% EXECUTING [33s]
:testdata-aspectj:aspectJ > Resolve dependencies of :testdata-aspectj:tools > aspectjtools-1.8.0.M1.pom
Ctrl + C [oracle@c7 spring-loaded-master]$ grep -ir 1.8.0.M1 . ./testdata-aspectj/build.gradle:def aspectjVersion = "1.8.0.M1"
change it to 1.8.0, since milestone repository can't be accessed!
Run again, [oracle@c7 spring-loaded-master]$ ./gradlew build -x test [oracle@c7 spring-loaded-master]$ find . -name 'springloaded*.jar' ./springloaded/build/libs/springloaded-1.3.0.BUILD-SNAPSHOT-sources.jar ./springloaded/build/libs/springloaded-1.3.0.BUILD-SNAPSHOT.jar ./springloaded/build/libs/springloaded-1.3.0.BUILD-SNAPSHOT-javadoc.jar
[oracle@c7 spring-loaded-master]$ pwd /home/oracle/spring-loaded-master
Create one WLS 14.1.1 domain with Oracle Jdk 1.8.0+, JAVA_OPTS="${JAVA_OPTS} -javaagent:/home/oracle/spring-loaded-master/springloaded/build/libs/springloaded-1.3.0.BUILD-SNAPSHOT.jar -noverify"
WLS gives (tested @12.2.1.4 / 14.1.1.0)
java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.__sljlcgdc(ObjectStreamClass.java)
at java.io.ObjectStreamClass.getExternalizableConstructor(ObjectStreamClass.java:1517)
at java.io.ObjectStreamClass.access$1400(ObjectStreamClass.java:79)
at java.io.ObjectStreamClass$3.run(ObjectStreamClass.java:517)
at java.io.ObjectStreamClass$3.run(ObjectStreamClass.java:494)
at java.security.AccessController.doPrivileged(Native Method)
at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:494)
at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:391)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1134)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at weblogic.messaging.dispatcher.DispatcherWrapper.writeExternal(DispatcherWrapper.java:208)
at java.io.ObjectOutputStream.writeExternalData(ObjectOutputStream.java:1459)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1430)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
...
Caused by: java.lang.NoSuchMethodException: weblogic.rmi.internal.CollocatedRemoteRef.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlClassGetDeclaredConstructor(ReflectiveInterceptor.java:477)
... 76 more
-- Summary -- class weblogic.rmi.internal.CollocatedRemoteRef. class has no default constructor, when de-serialization happens:
Agent change code behavior
- jdk code java.io.ObjectStreamClass.getExternalizableConstructor ignored NoSuchMethodException
- but org.springsource.loaded.ri.ReflectiveInterceptor.jlClassGetDeclaredConstructor throws it out
java.io.ObjectStreamClass.getExternalizableConstructor(ObjectStreamClass.java:1517) https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/io/ObjectStreamClass.java
1422 /**
1423 * Returns public no-arg constructor of given class, or null if none found.
1424 * Access checks are disabled on the returned constructor (if any), since
1425 * the defining class may still be non-public.
1426 */
1427 private static Constructor<?> getExternalizableConstructor(Class<?> cl) {
1428 try {
1429 Constructor<?> cons = cl.getDeclaredConstructor((Class<?>[]) null);
1430 cons.setAccessible(true);
1431 return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?
1432 cons : null;
1433 } catch (NoSuchMethodException ex) {
1434 return null;
1435 }
1436 }
Clearly, @line 1433 (not same jdk version, line # is different) get catched & ignored. But java.io.ObjectStreamClass get instrumented by default (And Yes, commenting out line 100~101 will supress this error, https://github.com/spring-projects/spring-loaded/blob/master/springloaded/src/main/java/org/springsource/loaded/agent/SpringLoadedPreProcessor.java
98 // Related to serialization
99 // TODO [serialization] Caches in ObjectStreamClass for descriptors, need clearing on reload
100 systemClassesContainingReflection.add("java/io/ObjectStreamClass");
101 systemClassesContainingReflection.add("java/io/ObjectStreamClass$EntryFuture");
The code path changes to
java.lang.Exception: @@@ by dev, clazz = weblogic.rmi.internal.CollocatedRemoteRef
at org.springsource.loaded.ri.ReflectiveInterceptor.jlClassGetDeclaredConstructor(ReflectiveInterceptor.java:475)
at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.__sljlcgdc(ObjectStreamClass.java)
at java.io.ObjectStreamClass.getExternalizableConstructor(ObjectStreamClass.java:1517)
ReflectiveInterceptor.jlClassGetDeclaredConstructor throws java.lang.NoSuchMethodException out, https://github.com/spring-projects/spring-loaded/blob/master/springloaded/src/main/java/org/springsource/loaded/ri/ReflectiveInterceptor.java
471 public static Constructor<?> jlClassGetDeclaredConstructor(Class<?> clazz, Class<?>... params)
472 throws SecurityException,
473 NoSuchMethodException {**
474 ReloadableType rtype = getRType(clazz);
475 if (rtype == null) {
476 // Non reloadable type
477 Constructor<?> c = clazz.getDeclaredConstructor(params); << Here !**
478 return c;
479 }