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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions