JDK-8264667 : string concatenation in class transformer causes LinkageError
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 9,17
  • Priority: P3
  • Status: Resolved
  • Resolution: Not an Issue
  • CPU: generic
  • Submitted: 2021-04-02
  • Updated: 2021-05-25
  • Resolved: 2021-05-25
Related Reports
Relates :  
Relates :  
Description
See attached testcase (Test1.java, InstrumentationHandoff.java, retransformAgent.mf)

> javac Test1.java
> javac InstrumentationHandoff.java
> jar cvfm retransformAgent.jar retransformAgent.mf InstrumentationHandoff.class
> java -XX:MaxRAMPercentage=12 -javaagent:retransformAgent.jar Test1

Results:
InstrumentationHandoff JPLIS agent initialized
>>addTransformerToManager
>>transform
>>transform
Exception in thread "main" >>transform
>>transform
>>transform
java.lang.ClassCircularityError: java/lang/invoke/MethodHandleImpl$AsVarargsCollector
>>transform
>>transform
        at java.base/java.lang.invoke.MethodHandleImpl.makeVarargsCollector(MethodHandleImpl.java:442)
        at java.base/java.lang.invoke.MethodHandle.asVarargsCollector(MethodHandle.java:1433)
        at java.base/java.lang.invoke.MethodHandle.withVarargs(MethodHandle.java:1114)
        at java.base/java.lang.invoke.MethodHandle.setVarargs(MethodHandle.java:1637)
        at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:3996)
        at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:3944)
        at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodForConstant(MethodHandles.java:4188)
        at java.base/java.lang.invoke.MethodHandles$Lookup.linkMethodHandleConstant(MethodHandles.java:4136)
        at java.base/java.lang.invoke.MethodHandleNatives.linkMethodHandleConstant(MethodHandleNatives.java:615)
        at Test1.addTransformerToManager(Test1.java:27)
        at Test1.runTest(Test1.java:18)
        at Test1.main(Test1.java:10)
>>transform
>>transform
>>transform
>>transform
>>transform
>>transform
>>transform
>>transform
>>transform
Comments
I still don't like the idea to make this agent developer responsibility, but it's unclear what we can do with this. The only solution I can imagine is to to make classes which are used for string concatenation (and maybe lambdas) "internal" and don't call transformers for such classes. But this maybe also not obvious behavior. So for now closing the issue as "not as issue".
25-05-2021

This seems related to the more general issues of CCE during transformation that I documented in JDK-8164165.
18-05-2021

I see that too. It looks like somehow the transformer doesn't try to transform the classes it loads (which is good) but it does get a duplicate class definition or CCE because it's trying to load a class that is already being loaded. I added a simple class C and C c = new C(); in both main and the transformer and get the same sort of error. We get ClassCircularityError because java/lang/invoke/MethodHandleImpl$AsVarargsCollector is in the bootstrap class loader (so has a check). We get duplicate class linkage error for the class C because it's loaded by the App$ClassLoader which doesn't check until the class is defined. I thought for redefinition and retransformation, since the user is manipulating bytecodes that we put the responsibility of knowing these implementation details like string concatenation on the user. We discussed this when we were adding code to disallow adding and deleting static private methods for RedefineClasses, since lambda expressions add private static methods. For the moment I can't think of how to handle this, and it's not really a classloading issue and more of a jvmti one, so I'm going to reclassify this bug, and give it to you.
09-04-2021

Just re-tested. if we have concatenation only in main thread, transformer is called for several Species classes (Species_LL, Species_LLL, Species_LLLL, Species_LLLLL, Species_LJ, Species_LLLLLL, Species_LLLLLLL). If we have concatenation only in tranformer, transformer is NOT called for Species classes.
09-04-2021

[~coleenp] Couple notes: 1. The transformer does not load classes directly. The fact that string concatenation causes class loading is an implementation detail, so it's hard to call user error. 2. The error occurs only if we have string concatenation in both transformer and in "main" thread (after addTransformer - see Test1.java:27). And as far as I remember normally transformers are not called for this "Species" classes (at least for concatenations in the transformer).
09-04-2021

I think this is a user error. They have a transformer that transforms all loaded classes, and the transformer loads classes. It's not necessarily a ClassCircularityError as a recursion error. We're seeing the same class loaded by the same thread twice.
09-04-2021

ILW = MMM = P3
06-04-2021

The issue is reproducible starting from jdk9 (but the exceptions are slightly different)
02-04-2021

JDK-8262002 has different exception in similar case: java.lang.LinkageError: loader 'bootstrap' attempted duplicate class definition for java.lang.invoke.BoundMethodHandle$Species_LLLLL. (java.lang.invoke.BoundMethodHandle$Species_LLLLL is in module java.base of loader 'bootstrap')
02-04-2021

The error occurs when we have string concatenations in main thread (which adds transformer, Test1.java:27) and in transformer (Test1.java:49)
02-04-2021