|
25 | 25 | */
|
26 | 26 | package com.oracle.svm.core.hub;
|
27 | 27 |
|
| 28 | +import static java.lang.classfile.ClassFile.ConstantPoolSharingOption.NEW_POOL; |
| 29 | + |
28 | 30 | import java.io.Serializable;
|
| 31 | +import java.lang.classfile.ClassFile; |
| 32 | +import java.lang.classfile.ClassModel; |
| 33 | +import java.lang.classfile.ClassTransform; |
| 34 | +import java.lang.classfile.MethodTransform; |
| 35 | +import java.lang.classfile.constantpool.ClassEntry; |
| 36 | +import java.lang.classfile.instruction.FieldInstruction; |
| 37 | +import java.lang.classfile.instruction.InvokeInstruction; |
| 38 | +import java.lang.classfile.instruction.NewMultiArrayInstruction; |
| 39 | +import java.lang.classfile.instruction.NewObjectInstruction; |
| 40 | +import java.lang.classfile.instruction.NewReferenceArrayInstruction; |
| 41 | +import java.lang.classfile.instruction.TypeCheckInstruction; |
| 42 | +import java.lang.constant.ClassDesc; |
29 | 43 | import java.lang.reflect.Method;
|
30 | 44 | import java.security.ProtectionDomain;
|
31 | 45 | import java.util.HashSet;
|
|
44 | 58 | import com.oracle.svm.core.reflect.serialize.SerializationSupport;
|
45 | 59 | import com.oracle.svm.core.util.ImageHeapMap;
|
46 | 60 | import com.oracle.svm.core.util.VMError;
|
47 |
| -import com.oracle.svm.shaded.org.objectweb.asm.ClassReader; |
48 |
| -import com.oracle.svm.shaded.org.objectweb.asm.ClassVisitor; |
49 |
| -import com.oracle.svm.shaded.org.objectweb.asm.ClassWriter; |
50 |
| -import com.oracle.svm.shaded.org.objectweb.asm.MethodVisitor; |
51 |
| -import com.oracle.svm.shaded.org.objectweb.asm.Opcodes; |
52 | 61 | import com.oracle.svm.util.ClassUtil;
|
53 | 62 |
|
54 | 63 | import jdk.graal.compiler.api.replacements.Fold;
|
@@ -332,41 +341,32 @@ public static Class<?> maybeAdjustLambdaNestHost(String className, Class<?> java
|
332 | 341 |
|
333 | 342 | @Platforms(Platform.HOSTED_ONLY.class)
|
334 | 343 | public static byte[] changeLambdaClassName(byte[] data, String oldName, String newName) {
|
335 |
| - ClassReader cr = new ClassReader(data); |
336 |
| - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); |
337 |
| - |
338 |
| - cr.accept(new ClassVisitor(Opcodes.ASM5, cw) { |
339 |
| - // Change lambda class name in the bytecode |
340 |
| - @Override |
341 |
| - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { |
342 |
| - super.visit(version, access, newName, signature, superName, interfaces); |
343 |
| - } |
344 |
| - |
345 |
| - // Change all class references in the lambda class bytecode |
346 |
| - @Override |
347 |
| - public MethodVisitor visitMethod(int access, String originalName, String desc, String signature, String[] exceptions) { |
348 |
| - return new MethodVisitor(Opcodes.ASM5, super.visitMethod(access, originalName, desc, signature, exceptions)) { |
349 |
| - @Override |
350 |
| - public void visitTypeInsn(int opcode, String type) { |
351 |
| - String name = type.equals(oldName) ? newName : type; |
352 |
| - super.visitTypeInsn(opcode, name); |
353 |
| - } |
354 |
| - |
355 |
| - @Override |
356 |
| - public void visitMethodInsn(int opcode, String owner, String methodName, String descriptor, boolean isInterface) { |
357 |
| - String name = owner.equals(oldName) ? newName : owner; |
358 |
| - super.visitMethodInsn(opcode, name, methodName, descriptor, isInterface); |
359 |
| - } |
360 |
| - |
361 |
| - @Override |
362 |
| - public void visitFieldInsn(int opcode, String owner, String fieldName, String descriptor) { |
363 |
| - String name = owner.equals(oldName) ? newName : owner; |
364 |
| - super.visitFieldInsn(opcode, name, fieldName, descriptor); |
365 |
| - } |
366 |
| - }; |
367 |
| - } |
368 |
| - }, ClassReader.EXPAND_FRAMES); |
369 |
| - |
370 |
| - return cw.toByteArray(); |
| 344 | + ClassDesc oldDesc = ClassDesc.ofInternalName(oldName); |
| 345 | + ClassDesc newDesc = ClassDesc.ofInternalName(newName); |
| 346 | + |
| 347 | + ClassFile classFile = ClassFile.of(NEW_POOL); |
| 348 | + ClassModel original = classFile.parse(data); |
| 349 | + |
| 350 | + return classFile.transformClass(original, newDesc, |
| 351 | + ClassTransform.transformingMethods( |
| 352 | + MethodTransform.transformingCode((builder, element) -> { |
| 353 | + ClassEntry newClassEntry = builder.constantPool().classEntry(newDesc); |
| 354 | + // Pass through any unhandled elements unchanged |
| 355 | + if (element instanceof TypeCheckInstruction ti && ti.type().asSymbol().equals(oldDesc)) { |
| 356 | + builder.with(TypeCheckInstruction.of(ti.opcode(), newClassEntry)); |
| 357 | + } else if (element instanceof NewObjectInstruction ti && ti.className().asSymbol().equals(oldDesc)) { |
| 358 | + builder.with(NewObjectInstruction.of(newClassEntry)); |
| 359 | + } else if (element instanceof NewReferenceArrayInstruction ti && ti.componentType().asSymbol().equals(oldDesc)) { |
| 360 | + builder.with(NewReferenceArrayInstruction.of(newClassEntry)); |
| 361 | + } else if (element instanceof NewMultiArrayInstruction ti && ti.arrayType().asSymbol().equals(oldDesc)) { |
| 362 | + builder.with(NewMultiArrayInstruction.of(newClassEntry, ti.dimensions())); |
| 363 | + } else if (element instanceof InvokeInstruction mi && mi.owner().asSymbol().equals(oldDesc)) { |
| 364 | + builder.with(InvokeInstruction.of(mi.opcode(), newClassEntry, mi.name(), mi.type(), mi.isInterface())); |
| 365 | + } else if (element instanceof FieldInstruction fi && fi.owner().asSymbol().equals(oldDesc)) { |
| 366 | + builder.with(FieldInstruction.of(fi.opcode(), newClassEntry, fi.name(), fi.type())); |
| 367 | + } else { |
| 368 | + builder.with(element); |
| 369 | + } |
| 370 | + }))); |
371 | 371 | }
|
372 | 372 | }
|
0 commit comments