WIP on Java8. Looking at lambda reloading first (required invokedynamic handling)

This commit is contained in:
Andy Clement
2014-02-13 10:39:32 -08:00
parent 8dff505b88
commit 9774e2a0d4
64 changed files with 745 additions and 140 deletions

View File

@@ -18,11 +18,10 @@ package org.springsource.loaded;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -54,7 +53,7 @@ public class ClassRenamer {
return renamed;
}
static class RenameAdapter extends ClassAdapter implements Opcodes {
static class RenameAdapter extends ClassVisitor implements Opcodes {
private ClassWriter cw;
private String oldname;
@@ -62,7 +61,7 @@ public class ClassRenamer {
private Map<String, String> retargets = new HashMap<String, String>();
public RenameAdapter(String newname, String[] retargets) {
super(new ClassWriter(0));
super(ASM5,new ClassWriter(0));
cw = (ClassWriter) cv;
this.newname = newname.replace('.', '/');
if (retargets != null) {
@@ -141,13 +140,13 @@ public class ClassRenamer {
return super.visitField(access, name, desc, signature, value);
}
class RenameMethodAdapter extends MethodAdapter implements Opcodes {
class RenameMethodAdapter extends MethodVisitor implements Opcodes {
String oldname;
String newname;
public RenameMethodAdapter(MethodVisitor mv, String oldname, String newname) {
super(mv);
super(ASM5,mv);
this.oldname = oldname;
this.newname = newname;
}

View File

@@ -81,6 +81,7 @@ public interface Constants extends Opcodes {
static String mChangedForInvokeInterfaceName = "iincheck";
static String mChangedForInvokeVirtualName = "ivicheck";
static String mChangedForInvokeSpecialName = "ispcheck";
static String mPerformInvokeDynamicName = "idyrun";
static String descriptorChangedForInvokeSpecialName = "(ILjava/lang/String;)Lorg/springsource/loaded/__DynamicallyDispatchable;";
static String mChangedForConstructorName = "ccheck";
@@ -103,6 +104,7 @@ public interface Constants extends Opcodes {
static int ACC_PUBLIC_PROTECTED = Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED;
static int ACC_PUBLIC_PRIVATE_PROTECTED = Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED;
static int ACC_PRIVATE_STATIC_SYNTHETIC = Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC;
static int ACC_PRIVATE_PROTECTED = Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED;
static int ACC_PRIVATE_STATIC_FINAL = ACC_FINAL | ACC_STATIC | ACC_PRIVATE;

View File

@@ -16,14 +16,13 @@
package org.springsource.loaded;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
/**
* @author Andy Clement
* @since 0.5.0
*/
class ConstructorCopier extends MethodAdapter implements Constants {
class ConstructorCopier extends MethodVisitor implements Constants {
private final static int preInvokeSpecial = 0;
private final static int postInvokeSpecial = 1;
@@ -39,7 +38,7 @@ class ConstructorCopier extends MethodAdapter implements Constants {
private String classname;
public ConstructorCopier(MethodVisitor mv, TypeDescriptor typeDescriptor, String suffix, String classname) {
super(mv);
super(ASM5,mv);
this.typeDescriptor = typeDescriptor;
this.suffix = suffix;
this.classname = classname;

View File

@@ -57,7 +57,7 @@ public class DispatcherBuilder {
/**
* Whilst visiting the interface, the implementation is created.
*/
static class DispatcherBuilderVisitor implements ClassVisitor, Opcodes, Constants {
static class DispatcherBuilderVisitor extends ClassVisitor implements Opcodes, Constants {
private ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
@@ -68,6 +68,7 @@ public class DispatcherBuilder {
private IncrementalTypeDescriptor typeDescriptor;
public DispatcherBuilderVisitor(ReloadableType rtype, IncrementalTypeDescriptor typeDescriptor, String suffix) {
super(ASM5);
this.classname = rtype.getSlashedName();
this.typeDescriptor = typeDescriptor;
this.suffix = suffix;

View File

@@ -27,7 +27,11 @@ import org.objectweb.asm.MethodVisitor;
* @author Andy Clement
* @since 0.7.3
*/
public class EmptyClassVisitor implements ClassVisitor, Constants {
public class EmptyClassVisitor extends ClassVisitor implements Constants {
public EmptyClassVisitor() {
super(ASM5);
}
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
}

View File

@@ -69,7 +69,7 @@ public class ExecutorBuilder {
* ClassVisitor that constructs the executor by visiting the original class. The basic goal is to visit the original class and
* 'copy' the methods into the executor, making adjustments as we go.
*/
static class ExecutorBuilderVisitor implements ClassVisitor, Constants {
static class ExecutorBuilderVisitor extends ClassVisitor implements Constants {
private ClassWriter cw = new ClassWriter(0);
@@ -78,6 +78,7 @@ public class ExecutorBuilder {
protected TypeDescriptor typeDescriptor;
public ExecutorBuilderVisitor(String classname, String suffix, TypeDescriptor typeDescriptor) {
super(ASM5);
this.classname = classname;
this.suffix = suffix;
this.typeDescriptor = typeDescriptor;
@@ -145,11 +146,12 @@ public class ExecutorBuilder {
cw.visitSource(sourcefile, debug);
}
private static class CopyingAnnotationVisitor implements AnnotationVisitor {
private static class CopyingAnnotationVisitor extends AnnotationVisitor {
private AnnotationVisitor av;
public CopyingAnnotationVisitor(AnnotationVisitor av) {
super(ASM5);
this.av = av;
}

View File

@@ -66,13 +66,14 @@ public class InterfaceExtractor {
return extractorVisitor.getBytes();
}
class ExtractorVisitor implements ClassVisitor, Constants {
class ExtractorVisitor extends ClassVisitor implements Constants {
private TypeDescriptor typeDescriptor;
private ClassWriter interfaceWriter = new ClassWriter(0);
private String slashedtypename;
public ExtractorVisitor(TypeDescriptor typeDescriptor) {
super(ASM5);
this.typeDescriptor = typeDescriptor;
}

View File

@@ -16,7 +16,6 @@
package org.springsource.loaded;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.springsource.loaded.Utils.ReturnType;
@@ -26,7 +25,7 @@ import org.springsource.loaded.Utils.ReturnType;
* @author Andy Clement
* @since 0.5.0
*/
class MethodCopier extends MethodAdapter implements Constants {
class MethodCopier extends MethodVisitor implements Constants {
private boolean isInterface;
private String descriptor;
@@ -37,7 +36,7 @@ class MethodCopier extends MethodAdapter implements Constants {
public MethodCopier(MethodVisitor mv, boolean isInterface, String descriptor, TypeDescriptor typeDescriptor, String classname,
String suffix) {
super(mv);
super(ASM5,mv);
this.isInterface = isInterface;
this.descriptor = descriptor;
this.typeDescriptor = typeDescriptor;

View File

@@ -30,13 +30,12 @@ import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.logging.Logger;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.springsource.loaded.ConstantPoolChecker2.References;
@@ -436,7 +435,7 @@ public class MethodInvokerRewriter {
static class DontRewriteException extends RuntimeException {
}
static class RewriteClassAdaptor extends ClassAdapter implements Opcodes {
static class RewriteClassAdaptor extends ClassVisitor implements Opcodes {
private ClassVisitor cw;
@@ -667,14 +666,14 @@ public class MethodInvokerRewriter {
return intercepted.contains(owner + "." + methodName);
}
private TypeRegistry typeRegistry;
protected TypeRegistry typeRegistry;
boolean isEnum = false;
private boolean isGroovyClosure = false;
int fieldcount = 0;
public RewriteClassAdaptor(TypeRegistry typeRegistry, ClassVisitor classWriter) {
// TODO should it also compute frames?
super(classWriter);
super(ASM5,classWriter);
cw = cv;
this.typeRegistry = typeRegistry;
}
@@ -691,7 +690,7 @@ public class MethodInvokerRewriter {
public ClassVisitor getClassVisitor() {
return cv;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
@@ -721,7 +720,7 @@ public class MethodInvokerRewriter {
return new RewritingMethodAdapter(mv, name);
}
class RewritingMethodAdapter extends MethodAdapter implements Opcodes, Constants {
class RewritingMethodAdapter extends MethodVisitor implements Opcodes, Constants {
// tracks max variable used in a method so we know what we can use
// safely
@@ -731,7 +730,7 @@ public class MethodInvokerRewriter {
private boolean isClinitOrEnumInit = false;
public RewritingMethodAdapter(MethodVisitor mv, String methodname) {
super(mv);
super(ASM5,mv);
this.methodname = methodname;
if (isEnum) {
isClinitOrEnumInit = this.methodname.length() > 2 && this.methodname.charAt(0) == '<'
@@ -950,6 +949,123 @@ public class MethodInvokerRewriter {
super.visitTypeInsn(opcode, type);
}
private String toString(Handle handle) {
return "handle(tag="+handle.getTag()+",name="+handle.getName()+",desc="+handle.getDesc()+",owner="+handle.getOwner();
}
private String toString(Object[] oa) {
StringBuilder buf = new StringBuilder();
buf.append("[");
if (oa!=null) {
for (Object o:oa) {
buf.append(" ");
buf.append(o);
}
}
buf.append("]");
return buf.toString();
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, org.objectweb.asm.Handle bsm, Object... bsmArgs) {
// TODO *shudder* what about invoke dynamic calls that target reflective APIs
boolean handled = false;
// TODO Perhaps (for sake of my sanity initially) make a distinction here between the general invokedynamic case and the special lambda support case?
// name=m
// desc=()Lbasic/LambdaA2$Foo;
// bsm=handle(tag=6,
// name=metafactory,
// desc=(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;,
// owner=java/lang/invoke/LambdaMetafactory
// bsmArgs=[ ()I basic/LambdaA2.lambda$run$1()I (6) ()I]
if (bsm.getTag()==H_INVOKESTATIC) {
// InvokeDynamic(name=m,desc=()Lbasic/LambdaA$Foo;,bsm=handle(tag=6,name=metafactory,desc=(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;,owner=java/lang/invoke/LambdaMetafactory,bsmArgs=[ ()I basic/LambdaA.lambda$run$0()I (6) ()I]
System.out.println("InvokeDynamic(name="+name+",desc="+desc+",bsm="+toString(bsm)+",bsmArgs="+toString(bsmArgs));
// The other invokes use the 'owner' of the target method to determine which type registry should be part of this
// check. Here the 'owner' is wrapped up in the bootstrap method - as version 1 we can assume the owner is the lambdametafactory
// which *wont* be getting reloaded - so we already know we don't need to do some jiggery pokery.
// int classId = typeRegistry.getTypeIdFor(owner, true);
// Call type registry to determine 'can we do what we were going to do?'
int bsmReferenceId = typeRegistry.recordBootstrapMethod(bsm,bsmArgs);
// Method java/lang/invoke/MethodHandles.lookup:()Ljava/lang/invoke/MethodHandles$Lookup;
mv.visitMethodInsn(INVOKESTATIC,"java/lang/invoke/MethodHandles","lookup","()Ljava/lang/invoke/MethodHandles$Lookup;");
mv.visitLdcInsn(name+desc); // Ljava/lang/String;
mv.visitLdcInsn(bsmReferenceId); // I
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mPerformInvokeDynamicName, "(Ljava/lang/Object;Ljava/lang/String;I)Ljava/lang/Object;");
handled=true;
// TODO handle return type
// mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(),classId));
// mv.visitLdcInsn(name+desc);
// mv.visitLdcInsn(BSM_NUMBER);
// mv.visitLdcInsn(bsmArgs);
// // What can we check to see whether it is necessary to intercept this call? Is it the return type of the descriptor? (For when
// // the bsm is recognizable as for lambda support)
// mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
// mv.visitLdcInsn(name + desc);
// mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeVirtualName, "(ILjava/lang/String;)Z");
// // Return value is the extracted interface to call if there is a
// // change and it can't be called directly
//
// // 2. preserve a copy of the return value (new target)
// // mv.visitInsn(DUP);
//
// // 3. Was it null?
// Label l1 = new Label();
// mv.visitJumpInsn(IFEQ, l1);
//
// // 4. Not false
//
// // 5. Store the target implementation of the interface that we
// // will invoke later
// // mv.visitVarInsn(ASTORE, max + 1);
//
// // 6. Package up any parameters
// if (hasParams) {
// Utils.collapseStackToArray(mv, desc);
// }
//
// // Prepare for the invocation:
// if (!hasParams) {
// // [targetInstance]
// mv.visitInsn(DUP);
// mv.visitInsn(ACONST_NULL); // no parameters
// mv.visitInsn(SWAP); // [targetInstance NULL targetInstance]
// } else {
// // [targetInstance paramArray]
// mv.visitInsn(SWAP);
// mv.visitInsn(DUP_X1); // [targetInstance paramArray
// // targetInstance]
// }
//
// mv.visitLdcInsn(name + desc);
//
// // calling __execute(params array,this,name+desc)
// mv.visitMethodInsn(INVOKEVIRTUAL, owner, mDynamicDispatchName, mDynamicDispatchDescriptor);
//
// insertAppropriateReturn(returnType);
// Label gotolabel = new Label();
// mv.visitJumpInsn(GOTO, gotolabel);
// mv.visitLabel(l1);
// // mv.visitInsn(POP);
// // Here is where we end up if the test for changes failed (ie.
// // there were no changes - just 'do what you were going to do'
// super.visitMethodInsn(opcode, owner, name, desc);
// mv.visitLabel(gotolabel);
}
else {
// TODO handle it!
}
if (!handled) {
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
}
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
if (GlobalConfiguration.interceptReflection && rewriteReflectiveCall(opcode, owner, name, desc)) {

View File

@@ -31,8 +31,8 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.springsource.loaded.MethodInvokerRewriter.DontRewriteException;
import org.springsource.loaded.MethodInvokerRewriter.RewriteClassAdaptor;
@@ -839,10 +839,10 @@ public class ReloadableType {
}
}
static class ChainedAdapters extends ClassAdapter implements Constants {
static class ChainedAdapters extends ClassVisitor implements Constants {
public ChainedAdapters(ReloadableType rtype) {
super(new RewriteClassAdaptor(rtype.typeRegistry, new TypeRewriter.RewriteClassAdaptor(rtype, new ClassWriter(
super(ASM5,new RewriteClassAdaptor(rtype.typeRegistry, new TypeRewriter.RewriteClassAdaptor(rtype, new ClassWriter(
ClassWriter.COMPUTE_MAXS))));
}

View File

@@ -15,10 +15,9 @@
*/
package org.springsource.loaded;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -39,7 +38,7 @@ public class SystemClassReflectionInvestigator {
return classAdaptor.hitCount;
}
static class RewriteClassAdaptor extends ClassAdapter implements Constants {
static class RewriteClassAdaptor extends ClassVisitor implements Constants {
int hitCount = 0;
private ClassWriter cw;
@@ -52,7 +51,7 @@ public class SystemClassReflectionInvestigator {
public RewriteClassAdaptor() {
// TODO should it also compute frames?
super(new ClassWriter(ClassWriter.COMPUTE_MAXS));
super(ASM5,new ClassWriter(ClassWriter.COMPUTE_MAXS));
cw = (ClassWriter) cv;
}
@@ -77,10 +76,10 @@ public class SystemClassReflectionInvestigator {
return new RewritingMethodAdapter(mv);
}
class RewritingMethodAdapter extends MethodAdapter implements Opcodes, Constants {
class RewritingMethodAdapter extends MethodVisitor implements Opcodes, Constants {
public RewritingMethodAdapter(MethodVisitor mv) {
super(mv);
super(ASM5,mv);
}
private boolean interceptReflection(String owner, String name, String desc) {

View File

@@ -18,12 +18,11 @@ package org.springsource.loaded;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -105,7 +104,7 @@ public class SystemClassReflectionRewriter {
}
}
static class RewriteClassAdaptor extends ClassAdapter implements Constants {
static class RewriteClassAdaptor extends ClassVisitor implements Constants {
private ClassWriter cw;
int bits = 0x0000;
@@ -122,7 +121,7 @@ public class SystemClassReflectionRewriter {
public RewriteClassAdaptor() {
// TODO should it also compute frames?
super(new ClassWriter(ClassWriter.COMPUTE_MAXS));
super(ASM5,new ClassWriter(ClassWriter.COMPUTE_MAXS));
cw = (ClassWriter) cv;
}
@@ -189,10 +188,10 @@ public class SystemClassReflectionRewriter {
}
}
class RewritingMethodAdapter extends MethodAdapter implements Opcodes, Constants {
class RewritingMethodAdapter extends MethodVisitor implements Opcodes, Constants {
public RewritingMethodAdapter(MethodVisitor mv) {
super(mv);
super(ASM5,mv);
}
/**

View File

@@ -54,7 +54,7 @@ public class TypeDescriptorExtractor {
/**
* Visit a class and accumulate sufficient information to build a TypeDescriptor.
*/
class ExtractionVisitor implements ClassVisitor, Opcodes {
class ExtractionVisitor extends ClassVisitor implements Opcodes {
private boolean isReloadableType;
private int flags;
@@ -72,6 +72,7 @@ public class TypeDescriptorExtractor {
private List<String> finalInHierarchy = new ArrayList<String>();
public ExtractionVisitor(boolean isReloadableType) {
super(ASM5);
this.isReloadableType = isReloadableType;
}

View File

@@ -15,6 +15,8 @@
*/
package org.springsource.loaded;
import j8code.J8Helper;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -42,6 +44,7 @@ import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.objectweb.asm.Handle;
import org.springsource.loaded.agent.FileSystemWatcher;
import org.springsource.loaded.agent.ReloadDecision;
import org.springsource.loaded.agent.ReloadableFileChangeListener;
@@ -1459,7 +1462,25 @@ public class TypeRegistry {
}
return false;
}
@UsedByGeneratedCode
public static Object idyrun(Object methodHandles_lookup, String nameAndDescriptor, int bsmId) {
// bsmId = 0
// nameAndDescriptor = m()Lbasic/LambdaA$Foo;
// 0: #31 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:
// (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;
// Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;
// Method arguments:
// #32 ()I
// #33 invokestatic basic/LambdaA.lambda$run$0:()I
// #32 ()I
System.out.println("idyrun("+methodHandles_lookup+","+nameAndDescriptor+","+bsmId+")");
return J8Helper.simulateInvokeDynamic(methodHandles_lookup);
}
/**
* Used in code the generated code replaces invokevirtual calls. Determine if the code can run as it was originally compiled.
*
@@ -1856,4 +1877,36 @@ public class TypeRegistry {
public Set<ReloadableType> getJDKProxiesFor(String slashedInterfaceTypeName) {
return jdkProxiesForInterface.get(slashedInterfaceTypeName);
}
/**
* When an invokedynamic instruction is reached, we allocate an id that
* recognizes that bsm and the parameters to that bsm. The index can be
* used when rewriting that invokedynamic
*
* @return id that represents this bootstrap method usage
*/
public synchronized int recordBootstrapMethod(Handle bsm, Object[] bsmArgs) {
// TODO [memory] search the existing bsmInfos for a matching one! Reuse!
if (nextBsmIndex >= bsmInfo.length) {
BsmInfo[] newarray = new BsmInfo[bsmInfo.length+4];
System.arraycopy(bsmInfo, 0, newarray, 0, bsmInfo.length);
bsmInfo = newarray;
}
bsmInfo[nextBsmIndex] = new BsmInfo(bsm,bsmArgs);
nextBsmIndex++;
return nextBsmIndex-1;
}
private int nextBsmIndex = 0;
private BsmInfo[] bsmInfo = new BsmInfo[4];
static class BsmInfo {
Handle bsm;
Object[] bsmArgs;
public BsmInfo(Handle bsm, Object[] bsmArgs) {
this.bsm = bsm;
this.bsmArgs = bsmArgs;
}
}
}

View File

@@ -19,13 +19,11 @@ import java.lang.reflect.Modifier;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.springsource.loaded.Utils.ReturnType;
@@ -55,7 +53,7 @@ public class TypeRewriter implements Constants {
return classAdaptor.getBytes();
}
static class RewriteClassAdaptor extends ClassAdapter implements Constants {
static class RewriteClassAdaptor extends ClassVisitor implements Constants {
private ClassWriter cw;
private String slashedname;
@@ -72,7 +70,7 @@ public class TypeRewriter implements Constants {
}
public RewriteClassAdaptor(ReloadableType rtype, ClassWriter classWriter) {
super(classWriter);
super(ASM5,classWriter);
this.rtype = rtype;
this.slashedname = rtype.getSlashedName();
this.cw = (ClassWriter) cv;
@@ -414,7 +412,7 @@ public class TypeRewriter implements Constants {
@Override
public MethodVisitor visitMethod(int flags, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(promoteIfNecessary(flags), name, descriptor, signature, exceptions);
MethodVisitor mv = super.visitMethod(promoteIfNecessary(flags,name), name, descriptor, signature, exceptions);
MethodVisitor newMethodVisitor = getMethodVisitor(name, descriptor, mv);
return newMethodVisitor;
}
@@ -444,8 +442,8 @@ public class TypeRewriter implements Constants {
}
// Default visibility elements need promotion to public so that they can be seen from the executor
private int promoteIfNecessary(int flags) {
int newflags = Utils.promoteDefaultOrProtectedToPublic(flags, isEnum);
private int promoteIfNecessary(int flags,String name) {
int newflags = Utils.promoteDefaultOrProtectedToPublic(flags, isEnum, name);
return newflags;
}
@@ -816,7 +814,7 @@ public class TypeRewriter implements Constants {
/**
* Rewrites a method to include the extra checks to verify it is the most up to date version.
*/
class AugmentingMethodAdapter extends MethodAdapter implements Opcodes {
class AugmentingMethodAdapter extends MethodVisitor implements Opcodes {
int methodId;
String name;
@@ -825,7 +823,7 @@ public class TypeRewriter implements Constants {
ReturnType returnType;
public AugmentingMethodAdapter(MethodVisitor mv, String name, String descriptor) {
super(mv);
super(ASM5,mv);
this.name = name;
this.method = rtype.getMethod(name, descriptor);
this.methodId = method.getId();
@@ -916,7 +914,7 @@ public class TypeRewriter implements Constants {
}
class AugmentingConstructorAdapter extends MethodAdapter implements Opcodes {
class AugmentingConstructorAdapter extends MethodVisitor implements Opcodes {
int ctorId;
String name;
@@ -926,7 +924,7 @@ public class TypeRewriter implements Constants {
boolean isTopMost;
public AugmentingConstructorAdapter(MethodVisitor mv, String descriptor, String type, boolean isTopMost) {
super(mv);
super(ASM5,mv);
this.descriptor = descriptor;
this.type = type;
this.isTopMost = isTopMost;
@@ -1053,12 +1051,12 @@ public class TypeRewriter implements Constants {
void prepend();
}
class MethodPrepender extends MethodAdapter implements Opcodes {
class MethodPrepender extends MethodVisitor implements Opcodes {
Prepender appender;
public MethodPrepender(MethodVisitor mv, Prepender appender) {
super(mv);
super(ASM5,mv);
this.appender = appender;
}

View File

@@ -1369,7 +1369,7 @@ public class Utils implements Opcodes, Constants {
return access;
}
public static int promoteDefaultOrProtectedToPublic(int access, boolean isEnum) {
public static int promoteDefaultOrProtectedToPublic(int access, boolean isEnum, String name) {
if ((access & Constants.ACC_PUBLIC_PRIVATE_PROTECTED) == 0) {
// is default
return (access | Modifier.PUBLIC);
@@ -1382,6 +1382,10 @@ public class Utils implements Opcodes, Constants {
// was private, need to 'publicize' it
return access - Constants.ACC_PRIVATE + Constants.ACC_PUBLIC;
}
if ((access&Constants.ACC_PRIVATE_STATIC_SYNTHETIC)==ACC_PRIVATE_STATIC_SYNTHETIC && name.startsWith("lambda")) {
// Special case for lambda, may need to generalize for general invokedynamic support
return access - Constants.ACC_PRIVATE + Constants.ACC_PUBLIC;
}
return access;
}
@@ -1733,7 +1737,11 @@ public class Utils implements Opcodes, Constants {
// TODO [performance] speed up by throwing exception from first visit method? (but this isn't used in the mainline really)
// TODO or just write a quicker bytecode parser that just looks at the interfaces then returns
private static class InterfaceCollectingClassVisitor implements ClassVisitor {
private static class InterfaceCollectingClassVisitor extends ClassVisitor {
public InterfaceCollectingClassVisitor() {
super(ASM5);
}
public String[] interfaces;

View File

@@ -19,10 +19,9 @@ import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.springsource.loaded.Constants;
@@ -33,7 +32,7 @@ import org.springsource.loaded.Constants;
* @author Andy Clement
* @since 0.8.3
*/
public class CglibPluginCapturing extends ClassAdapter implements Constants {
public class CglibPluginCapturing extends ClassVisitor implements Constants {
public static Map<Class<?>, Object[]> clazzToGeneratorStrategyAndClassGeneratorMap = new HashMap<Class<?>, Object[]>();
public static Map<Class<?>, Object[]> clazzToGeneratorStrategyAndFastClassGeneratorMap = new HashMap<Class<?>, Object[]>();
@@ -48,7 +47,7 @@ public class CglibPluginCapturing extends ClassAdapter implements Constants {
}
private CglibPluginCapturing() {
super(new ClassWriter(0)); // TODO review 0 here
super(ASM5,new ClassWriter(0)); // TODO review 0 here
}
@Override
@@ -74,10 +73,10 @@ public class CglibPluginCapturing extends ClassAdapter implements Constants {
}
}
class CreateMethodInterceptor extends MethodAdapter implements Constants {
class CreateMethodInterceptor extends MethodVisitor implements Constants {
public CreateMethodInterceptor(MethodVisitor mv) {
super(mv);
super(ASM5,mv);
}
@Override

View File

@@ -15,9 +15,8 @@
*/
package org.springsource.loaded.agent;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.springsource.loaded.Constants;
@@ -27,7 +26,7 @@ import org.springsource.loaded.Constants;
* @author Andy Clement
* @since 0.5.0
*/
public class ClassVisitingConstructorAppender extends ClassAdapter implements Constants {
public class ClassVisitingConstructorAppender extends ClassVisitor implements Constants {
private String calleeOwner;
private String calleeName;
@@ -41,7 +40,7 @@ public class ClassVisitingConstructorAppender extends ClassAdapter implements Co
* @param name
*/
public ClassVisitingConstructorAppender(String owner, String name) {
super(new ClassWriter(0)); // TODO review 0 here
super(ASM5,new ClassWriter(0)); // TODO review 0 here
this.calleeOwner = owner;
this.calleeName = name;
}
@@ -63,10 +62,10 @@ public class ClassVisitingConstructorAppender extends ClassAdapter implements Co
* This constructor appender includes a couple of instructions at the end of each constructor it is asked to visit. It
* recognizes the end by observing a RETURN instruction. The instructions are inserted just before the RETURN.
*/
class ConstructorAppender extends MethodAdapter implements Constants {
class ConstructorAppender extends MethodVisitor implements Constants {
public ConstructorAppender(MethodVisitor mv) {
super(mv);
super(ASM5,mv);
}
@Override

View File

@@ -15,7 +15,7 @@
*/
package org.springsource.loaded.agent;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.springsource.loaded.Constants;
@@ -26,12 +26,12 @@ import org.springsource.loaded.Constants;
* @author Andy Clement
* @since 0.7.0
*/
public class FalseReturner extends ClassAdapter implements Constants {
public class FalseReturner extends ClassVisitor implements Constants {
private String methodname;
public FalseReturner(String methodname) {
super(new ClassWriter(0)); // TODO review 0 here
super(ASM5,new ClassWriter(0)); // TODO review 0 here
this.methodname = methodname;
}

View File

@@ -15,9 +15,8 @@
*/
package org.springsource.loaded.agent;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodAdapter;
import org.objectweb.asm.MethodVisitor;
import org.springsource.loaded.Constants;
import org.springsource.loaded.GlobalConfiguration;
@@ -30,10 +29,10 @@ import org.springsource.loaded.TypeRegistry;
* @author Andy Clement
* @since 0.7.3
*/
public class ModifyDefineInClassLoaderForClassArtifactsType extends ClassAdapter implements Constants {
public class ModifyDefineInClassLoaderForClassArtifactsType extends ClassVisitor implements Constants {
public ModifyDefineInClassLoaderForClassArtifactsType() {
super(new ClassWriter(0)); // TODO review 0 here
super(ASM5,new ClassWriter(0)); // TODO review 0 here
}
public byte[] getBytes() {
@@ -49,10 +48,10 @@ public class ModifyDefineInClassLoaderForClassArtifactsType extends ClassAdapter
}
}
class DefineClassModifierVisitor extends MethodAdapter implements Constants {
class DefineClassModifierVisitor extends MethodVisitor implements Constants {
public DefineClassModifierVisitor(MethodVisitor mv) {
super(mv);
super(ASM5,mv);
}
@Override

View File

@@ -17,7 +17,7 @@ package org.springsource.loaded.agent;
import java.lang.reflect.Modifier;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.springsource.loaded.Constants;
@@ -29,7 +29,7 @@ import org.springsource.loaded.Constants;
* @author Andy Clement
* @since 0.7.0
*/
public class NonFinalizer extends ClassAdapter implements Constants {
public class NonFinalizer extends ClassVisitor implements Constants {
private String fieldname;
@@ -42,7 +42,7 @@ public class NonFinalizer extends ClassAdapter implements Constants {
* @param name
*/
public NonFinalizer(String fieldname) {
super(new ClassWriter(0)); // TODO review 0 here
super(ASM5,new ClassWriter(0)); // TODO review 0 here
this.fieldname = fieldname;
}

View File

@@ -17,8 +17,8 @@ package org.springsource.loaded.pluginhelpers;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
@@ -32,7 +32,7 @@ import org.springsource.loaded.test.infra.ClassPrinter;
* @author Andy Clement
* @since 0.8.3
*/
public class EmptyCtor extends ClassAdapter implements Constants {
public class EmptyCtor extends ClassVisitor implements Constants {
private String[] descriptors;
@@ -52,7 +52,7 @@ public class EmptyCtor extends ClassAdapter implements Constants {
}
private EmptyCtor(String... descriptors) {
super(new ClassWriter(0)); // TODO review 0 here
super(ASM5,new ClassWriter(0)); // TODO review 0 here
this.descriptors = descriptors;
}
@@ -80,11 +80,12 @@ public class EmptyCtor extends ClassAdapter implements Constants {
}
}
static class Emptier implements MethodVisitor, Constants {
static class Emptier extends MethodVisitor implements Constants {
MethodVisitor mv;
public Emptier(MethodVisitor mv) {
super(ASM5);
this.mv = mv;
}

View File

@@ -32,7 +32,7 @@ import org.springsource.loaded.Utils;
/**
* @author Andy Clement
*/
public class ClassPrinter implements ClassVisitor, Opcodes {
public class ClassPrinter extends ClassVisitor implements Opcodes {
private PrintStream destination;
private boolean includeBytecode;
@@ -47,6 +47,7 @@ public class ClassPrinter implements ClassVisitor, Opcodes {
}
public ClassPrinter(PrintStream destination, boolean includeBytecode) {
super(ASM5);
this.destination = destination;
this.includeBytecode = includeBytecode;
}
@@ -188,7 +189,11 @@ public class ClassPrinter implements ClassVisitor, Opcodes {
return new AnnotationVisitorPrinter();
}
class AnnotationVisitorPrinter implements AnnotationVisitor {
class AnnotationVisitorPrinter extends AnnotationVisitor {
public AnnotationVisitorPrinter() {
super(ASM5);
}
public void visit(String name, Object value) {
destination.print(name + "=" + value + " ");

View File

@@ -21,17 +21,17 @@ import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.springsource.loaded.Utils;
/**
*
* @author Andy Clement
*/
public class MethodPrinter implements MethodVisitor, Opcodes {
public class MethodPrinter extends MethodVisitor implements Opcodes {
PrintStream to;
@@ -47,12 +47,22 @@ public class MethodPrinter implements MethodVisitor, Opcodes {
}
public MethodPrinter(PrintStream destination) {
super(ASM5);
this.to = destination;
}
public void visitCode() {
to.print(" CODE\n");
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, org.objectweb.asm.Handle bsm, Object... bsmArgs) {
to.println(" INVOKEDYNAMIC " + name+"."+desc+" bsm="+toString(bsm));
}
private String toString(Handle bsm) {
return "#"+bsm.getTag()+" "+bsm.getOwner()+"."+bsm.getName()+bsm.getDesc();
}
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
if (opcode == Opcodes.INVOKESTATIC) {
@@ -75,7 +85,11 @@ public class MethodPrinter implements MethodVisitor, Opcodes {
return new AnnotationVisitorPrinter();
}
class AnnotationVisitorPrinter implements AnnotationVisitor {
class AnnotationVisitorPrinter extends AnnotationVisitor {
public AnnotationVisitorPrinter() {
super(ASM5);
}
public void visit(String name, Object value) {
to.print(name + "=" + value + " ");