Skip to content

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

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     } 

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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