spring-loaded icon indicating copy to clipboard operation
spring-loaded copied to clipboard

NoSuchMethodException is thrown by ReflectiveInterceptor.jlClassGetDeclaredConstructor which changes jdk code behavior

Open mingxhu opened this issue 2 years ago • 0 comments

-- 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     } 

mingxhu avatar Aug 23 '22 03:08 mingxhu