Skip to content

Commit dee1415

Browse files
committed
IDEA-364385 Instrumentation failure when using sealed types with @Async.Schedule
1 parent 3db23a3 commit dee1415

7 files changed

+59
-48
lines changed

src/main/java/com/intellij/rt/debugger/agent/CaptureAgent.java

+2-8
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,8 @@ public byte[] transform(ClassLoader loader,
105105
List<InstrumentPoint> classPoints = myInstrumentPoints.get(className);
106106
if (classPoints != null) {
107107
try {
108-
ClassReader reader = new ClassReader(classfileBuffer);
109-
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
110-
111-
reader.accept(new CaptureInstrumentor(Opcodes.API_VERSION, writer, classPoints), 0);
112-
113-
byte[] bytes = writer.toByteArray();
114-
storeClassForDebug(className, bytes);
115-
return bytes;
108+
ClassTransformer transformer = new ClassTransformer(className, classfileBuffer, ClassWriter.COMPUTE_FRAMES, loader);
109+
return transformer.accept(new CaptureInstrumentor(Opcodes.API_VERSION, transformer.writer, classPoints), 0, true);
116110
}
117111
catch (Exception e) {
118112
System.out.println("Capture agent: failed to instrument " + className);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.intellij.rt.debugger.agent;
2+
3+
import org.jetbrains.capture.org.objectweb.asm.ClassReader;
4+
import org.jetbrains.capture.org.objectweb.asm.ClassVisitor;
5+
import org.jetbrains.capture.org.objectweb.asm.ClassWriter;
6+
7+
public class ClassTransformer {
8+
private final String className;
9+
private final ClassReader reader;
10+
final ClassWriter writer;
11+
12+
public ClassTransformer(String className, byte[] classfileBuffer, int flags, final ClassLoader loader) {
13+
this.className = className;
14+
reader = new ClassReader(classfileBuffer);
15+
writer = new ClassWriter(reader, flags) {
16+
@Override
17+
protected ClassLoader getClassLoader() {
18+
return loader;
19+
}
20+
};
21+
}
22+
23+
public byte[] accept(ClassVisitor visitor, int parsingOptions, boolean storeClassForDebug) {
24+
reader.accept(visitor, parsingOptions);
25+
byte[] bytes = writer.toByteArray();
26+
if (storeClassForDebug) {
27+
CaptureAgent.storeClassForDebug(className, bytes);
28+
}
29+
return bytes;
30+
}
31+
}

src/main/java/com/intellij/rt/debugger/agent/CollectionBreakpointInstrumentor.java

+3-12
Original file line numberDiff line numberDiff line change
@@ -481,18 +481,9 @@ public byte[] transform(ClassLoader loader,
481481

482482
if (myCollectionsToTransform.containsKey(className) || myClassesToTransform.contains(className)) {
483483
try {
484-
ClassReader reader = new ClassReader(classfileBuffer);
485-
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
486-
487-
MyClassVisitor instrumentor = new MyClassVisitor(className, Opcodes.API_VERSION, writer);
488-
reader.accept(instrumentor, ClassReader.EXPAND_FRAMES);
489-
byte[] bytes = writer.toByteArray();
490-
491-
if (DEBUG) {
492-
writeDebugInfo(className, bytes);
493-
}
494-
495-
return bytes;
484+
ClassTransformer transformer = new ClassTransformer(className, classfileBuffer, ClassWriter.COMPUTE_FRAMES, loader);
485+
return transformer.accept(new MyClassVisitor(className, Opcodes.API_VERSION, transformer.writer),
486+
ClassReader.EXPAND_FRAMES, true);
496487
}
497488
catch (Exception e) {
498489
processFailedToInstrumentError(className, e);

src/main/java/com/intellij/rt/debugger/agent/SharedFlowTransformer.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.intellij.rt.debugger.agent;
22

3-
import org.jetbrains.capture.org.objectweb.asm.*;
3+
import org.jetbrains.capture.org.objectweb.asm.ClassVisitor;
4+
import org.jetbrains.capture.org.objectweb.asm.MethodVisitor;
5+
import org.jetbrains.capture.org.objectweb.asm.Opcodes;
46

57
import java.lang.instrument.ClassFileTransformer;
68
import java.security.ProtectionDomain;
@@ -13,10 +15,9 @@ public byte[] transform(final ClassLoader loader, String className, Class<?> cla
1315
if (!"kotlinx/coroutines/flow/internal/FlowValueWrapperInternalKt".equals(className)) {
1416
return classfileBuffer;
1517
}
16-
ClassReader reader = new ClassReader(classfileBuffer);
17-
ClassWriter writer = new ClassWriter(reader, 0);
18+
ClassTransformer transformer = new ClassTransformer(className, classfileBuffer, 0, loader);
1819
final boolean[] isLatestStableIjFork = { false };
19-
reader.accept(new ClassVisitor(Opcodes.API_VERSION, writer) {
20+
byte[] bytes = transformer.accept(new ClassVisitor(Opcodes.API_VERSION, transformer.writer) {
2021
@Override
2122
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
2223
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
@@ -31,13 +32,12 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
3132
}
3233
return mv;
3334
}
34-
}, 0);
35+
}, 0, false);
3536

3637
if (!isLatestStableIjFork[0]) {
3738
return classfileBuffer;
3839
}
3940

40-
byte[] bytes = writer.toByteArray();
4141
CaptureAgent.storeClassForDebug(className, bytes);
4242
return bytes;
4343
}

src/main/java/com/intellij/rt/debugger/agent/SpilledVariablesTransformer.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.intellij.rt.debugger.agent;
22

3-
import org.jetbrains.capture.org.objectweb.asm.*;
3+
import org.jetbrains.capture.org.objectweb.asm.ClassVisitor;
4+
import org.jetbrains.capture.org.objectweb.asm.ClassWriter;
5+
import org.jetbrains.capture.org.objectweb.asm.MethodVisitor;
6+
import org.jetbrains.capture.org.objectweb.asm.Opcodes;
47

58
import java.lang.instrument.ClassFileTransformer;
69
import java.lang.instrument.Instrumentation;
@@ -34,9 +37,8 @@ public byte[] transform(final ClassLoader loader, String className, Class<?> cla
3437
return classfileBuffer;
3538
}
3639
try {
37-
ClassReader reader = new ClassReader(classfileBuffer);
38-
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
39-
reader.accept(new ClassVisitor(Opcodes.API_VERSION, writer) {
40+
ClassTransformer transformer = new ClassTransformer(className, classfileBuffer, ClassWriter.COMPUTE_FRAMES, loader);
41+
return transformer.accept(new ClassVisitor(Opcodes.API_VERSION, transformer.writer) {
4042
@Override
4143
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
4244
MethodVisitor superMethodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
@@ -52,10 +54,7 @@ public void visitCode() {
5254
}
5355
return superMethodVisitor;
5456
}
55-
}, 0);
56-
byte[] bytes = writer.toByteArray();
57-
CaptureAgent.storeClassForDebug(className, bytes);
58-
return bytes;
57+
}, 0, true);
5958
} catch (Exception e) {
6059
System.out.println("SpillingTransformer: failed to instrument " + className);
6160
e.printStackTrace();

src/main/java/com/intellij/rt/debugger/agent/StateFlowTransformer.java

+3-5
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ public byte[] transform(final ClassLoader loader, String className, Class<?> cla
1111
if (!"kotlinx/coroutines/flow/StateFlowImpl".equals(className)) {
1212
return classfileBuffer;
1313
}
14-
ClassReader reader = new ClassReader(classfileBuffer);
15-
ClassWriter writer = new ClassWriter(reader, 0);
14+
ClassTransformer transformer = new ClassTransformer(className, classfileBuffer, 0, loader);
1615
// Here, we want to check two things:
1716
// - we instrument IJ fork of the coroutine library;
1817
// - we only instrument the latest version of the IJ fork (the only stable one).
@@ -23,7 +22,7 @@ public byte[] transform(final ClassLoader loader, String className, Class<?> cla
2322
// - and emitInner is not (then isLatestStableIjFork = true)
2423
final boolean[] isIjFork = { false };
2524
final boolean[] isLatestStableIjFork = { true };
26-
reader.accept(new ClassVisitor(Opcodes.API_VERSION, writer) {
25+
byte[] bytes = transformer.accept(new ClassVisitor(Opcodes.API_VERSION, transformer.writer) {
2726
@Override
2827
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
2928
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
@@ -54,15 +53,14 @@ public boolean test(int opcode, String owner, String name, String descriptor) {
5453
}
5554
return mv;
5655
}
57-
}, 0);
56+
}, 0, false);
5857

5958
boolean shouldTransform = isIjFork[0] && isLatestStableIjFork[0];
6059

6160
if (!shouldTransform) {
6261
return classfileBuffer;
6362
}
6463

65-
byte[] bytes = writer.toByteArray();
6664
CaptureAgent.storeClassForDebug(className, bytes);
6765
return bytes;
6866
}

src/main/java/com/intellij/rt/debugger/agent/ThrowableTransformer.java

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.intellij.rt.debugger.agent;
22

3-
import org.jetbrains.capture.org.objectweb.asm.*;
3+
import org.jetbrains.capture.org.objectweb.asm.ClassVisitor;
4+
import org.jetbrains.capture.org.objectweb.asm.ClassWriter;
5+
import org.jetbrains.capture.org.objectweb.asm.MethodVisitor;
6+
import org.jetbrains.capture.org.objectweb.asm.Opcodes;
47

58
import java.lang.instrument.ClassFileTransformer;
69
import java.security.ProtectionDomain;
@@ -17,10 +20,9 @@ public byte[] transform(ClassLoader loader,
1720
byte[] classfileBuffer) {
1821
if (THROWABLE_NAME.equals(className)) {
1922
try {
20-
ClassReader reader = new ClassReader(classfileBuffer);
21-
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
23+
ClassTransformer transformer = new ClassTransformer(className, classfileBuffer, ClassWriter.COMPUTE_FRAMES, loader);
2224

23-
reader.accept(new ClassVisitor(Opcodes.API_VERSION, writer) {
25+
return transformer.accept(new ClassVisitor(Opcodes.API_VERSION, transformer.writer) {
2426
@Override
2527
public MethodVisitor visitMethod(final int access, String name, String descriptor, String signature, String[] exceptions) {
2628
MethodVisitor superMethodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);
@@ -58,11 +60,7 @@ public void visitMethodInsn(int opcode, String owner, String name, String descri
5860
return superMethodVisitor;
5961
}
6062
}
61-
}, 0);
62-
63-
byte[] bytes = writer.toByteArray();
64-
CaptureAgent.storeClassForDebug(className, bytes);
65-
return bytes;
63+
}, 0, true);
6664
}
6765
catch (Exception e) {
6866
System.out.println("Capture agent: failed to instrument " + className);

0 commit comments

Comments
 (0)