Skip to content

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

@mingxhu

Description

@mingxhu

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions