Upgrade to asm-5.0.2

This ASM has a different visitMethodInsn() instruction so
there are big changes throughout the code. The tests are running
fine but as new testcases are added related to Java8 we may need
further fixes to take account of the extra isInterface parameter
on visitMethodInsn()
This commit is contained in:
Andy Clement
2014-05-15 12:36:13 -07:00
parent 8f74625829
commit 0787767b09
26 changed files with 132 additions and 118 deletions

View File

@@ -2,9 +2,9 @@
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="lib" path="lib/asm-5.0_BETA.jar"/>
<classpathentry kind="lib" path="lib/asm-tree-5.0_BETA.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J180_b128"/>
<classpathentry kind="lib" path="lib/asm-5.0.2.jar" sourcepath="lib/asm-5.0.2-sources.zip"/>
<classpathentry kind="lib" path="lib/asm-tree-5.0.2.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/j180_b128"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -41,8 +41,8 @@ task wrapper(type: Wrapper) {
dependencies {
tools 'com.googlecode.jarjar:jarjar:1.3'
compile 'org.ow2.asm:asm:5.0_BETA'
compile 'org.ow2.asm:asm-tree:5.0_BETA'
compile 'org.ow2.asm:asm:5.0.2'
compile 'org.ow2.asm:asm-tree:5.0.2'
testCompile 'junit:junit:4.11'

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -271,7 +271,7 @@ public class ClassRenamer {
mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (owner.equals(oldname)) {
owner = newname;
} else {
@@ -282,7 +282,7 @@ public class ClassRenamer {
} else {
desc = checkIfShouldBeRewritten(desc);
}
mv.visitMethodInsn(opcode, owner, name, desc);
mv.visitMethodInsn(opcode, owner, name, desc, itf);
}
private String checkIfShouldBeRewritten(String desc) {

View File

@@ -67,8 +67,9 @@ class ConstructorCopier extends MethodVisitor implements Constants {
super.visitTypeInsn(opcode, type);
}
// TODO may need to pay attention itf==true
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, boolean itf) {
// If this is an invokespecial, first determine if it is the one of interest (the one calling our super constructor)
if (opcode == INVOKESPECIAL && name.charAt(0) == '<') {
if (unitializedObjectsCount != 0) {
@@ -114,11 +115,11 @@ class ConstructorCopier extends MethodVisitor implements Constants {
// no stack is instance then params then instance
mv.visitLdcInsn("<init>" + desc);
mv.visitMethodInsn(INVOKESPECIAL, typeDescriptor.getSupertypeName(), mDynamicDispatchName,
mDynamicDispatchDescriptor);
mDynamicDispatchDescriptor, false);
mv.visitInsn(POP);
} else {
// it did exist in the original, so there will be parallel constructor
mv.visitMethodInsn(INVOKESPECIAL, typeDescriptor.getSupertypeName(), mInitializerName, desc);
mv.visitMethodInsn(INVOKESPECIAL, typeDescriptor.getSupertypeName(), mInitializerName, desc, false);
}
}
}
@@ -134,19 +135,19 @@ class ConstructorCopier extends MethodVisitor implements Constants {
if (opcode == INVOKESPECIAL && name.charAt(0) != '<' && owner.equals(classname) && !name.startsWith("r$")) {
// leaving the invokespecial alone will cause a verify error
String descriptor = Utils.insertExtraParameter(owner, desc);
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, descriptor);
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, descriptor, false);
} else {
boolean done = false;
// TODO dup of code in method copier - can we refactor?
if (opcode == INVOKESTATIC) {
MethodMember mm = typeDescriptor.getByDescriptor(name, desc);
if (mm != null && mm.isPrivate()) {
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, desc);
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, desc, false);
done = true;
}
}
if (!done) {
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
}

View File

@@ -91,7 +91,7 @@ public class DispatcherBuilder {
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
@@ -100,7 +100,7 @@ public class DispatcherBuilder {
private void generateClinitDispatcher() {
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, mStaticInitializerName, "()V", null, null);
mv.visitCode();
mv.visitMethodInsn(INVOKESTATIC, executorClassName, mStaticInitializerName, "()V");
mv.visitMethodInsn(INVOKESTATIC, executorClassName, mStaticInitializerName, "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
@@ -175,7 +175,7 @@ public class DispatcherBuilder {
// 2. Load the input name+descriptor and compare it with this method:
mv.visitVarInsn(ALOAD, 3);
mv.visitLdcInsn(nameWithDescriptor);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
Label label = new Label();
mv.visitJumpInsn(IFEQ, label); // means if false
@@ -196,7 +196,7 @@ public class DispatcherBuilder {
Utils.generateInstructionsToUnpackArrayAccordingToDescriptor(mv, method.descriptor, 1);
ReturnType returnType = Utils.getReturnTypeDescriptor(method.descriptor);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, executorClassName, method.name, callDescriptor);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, executorClassName, method.name, callDescriptor, false);
if (returnType.isVoid()) {
mv.visitInsn(ACONST_NULL);
} else if (returnType.isPrimitive()) {
@@ -212,7 +212,7 @@ public class DispatcherBuilder {
// if (nameAndDescriptor.equals(xxx)) {
mv.visitVarInsn(ALOAD, indexNameAndDescriptor);
mv.visitLdcInsn(nameWithDescriptor);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
Label label = new Label();
mv.visitJumpInsn(IFEQ, label); // means if false
@@ -230,7 +230,7 @@ public class DispatcherBuilder {
Utils.generateInstructionsToUnpackArrayAccordingToDescriptor(mv, ctor.descriptor, 1);
// ReturnType returnType = Utils.getReturnTypeDescriptor(method.descriptor);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, executorClassName, "___init___", callDescriptor);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, executorClassName, "___init___", callDescriptor, false);
// if (returnType.isVoid()) {
mv.visitInsn(ACONST_NULL);
// } else if (returnType.isPrimitive()) {
@@ -254,7 +254,7 @@ public class DispatcherBuilder {
// getDispatcher will give us the dispatcher for the supertype
mv.visitFieldInsn(Opcodes.GETSTATIC, slashedSupertypeName, fReloadableTypeFieldName, lReloadableType);
mv.visitMethodInsn(INVOKEVIRTUAL, tReloadableType, "getDispatcher",
"()Lorg/springsource/loaded/__DynamicallyDispatchable;");
"()Lorg/springsource/loaded/__DynamicallyDispatchable;", false);
// alternative 2: find the right dispatcher - i.e. who in the super hierarchy provides that nameAndDescriptor
@@ -262,7 +262,7 @@ public class DispatcherBuilder {
mv.visitVarInsn(ALOAD, indexArgs);
mv.visitVarInsn(ALOAD, indexTarget);
mv.visitVarInsn(ALOAD, indexNameAndDescriptor);
mv.visitMethodInsn(INVOKEINTERFACE, tDynamicallyDispatchable, mDynamicDispatchName, mDynamicDispatchDescriptor);
mv.visitMethodInsn(INVOKEINTERFACE, tDynamicallyDispatchable, mDynamicDispatchName, mDynamicDispatchDescriptor, false);
mv.visitInsn(ARETURN);
// mv.visitTypeInsn(NEW, "java/lang/IllegalStateException");
@@ -313,7 +313,7 @@ public class DispatcherBuilder {
int params = Utils.getParameterCount(descriptor);
String callDescriptor = isStatic ? originalDescriptor : descriptor;
Utils.createLoadsBasedOnDescriptor(mv, callDescriptor, isStatic ? 2 : 1);
mv.visitMethodInsn(INVOKESTATIC, executorClassName, name, callDescriptor);
mv.visitMethodInsn(INVOKESTATIC, executorClassName, name, callDescriptor, false);
Utils.addCorrectReturnInstruction(mv, returnTypeDescriptor, false);
mv.visitMaxs(params, params + 1);
mv.visitEnd();

View File

@@ -108,16 +108,16 @@ class MethodCopier extends MethodVisitor implements Constants {
if (fm != null) {
switch (opcode) {
case GETFIELD:
mv.visitMethodInsn(INVOKEVIRTUAL, classname, Utils.getProtectedFieldGetterName(name), "()" + desc);
mv.visitMethodInsn(INVOKEVIRTUAL, classname, Utils.getProtectedFieldGetterName(name), "()" + desc, false);
return;
case PUTFIELD:
mv.visitMethodInsn(INVOKEVIRTUAL, classname, Utils.getProtectedFieldSetterName(name), "(" + desc + ")V");
mv.visitMethodInsn(INVOKEVIRTUAL, classname, Utils.getProtectedFieldSetterName(name), "(" + desc + ")V", false);
return;
case GETSTATIC:
mv.visitMethodInsn(INVOKESTATIC, classname, Utils.getProtectedFieldGetterName(name), "()" + desc);
mv.visitMethodInsn(INVOKESTATIC, classname, Utils.getProtectedFieldGetterName(name), "()" + desc, false);
return;
case PUTSTATIC:
mv.visitMethodInsn(INVOKESTATIC, classname, Utils.getProtectedFieldSetterName(name), "(" + desc + ")V");
mv.visitMethodInsn(INVOKESTATIC, classname, Utils.getProtectedFieldSetterName(name), "(" + desc + ")V", false);
return;
}
}
@@ -125,8 +125,9 @@ class MethodCopier extends MethodVisitor implements Constants {
super.visitFieldInsn(opcode, owner, name, desc);
}
// TODO maybe do something if 'itf==true'
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, boolean itf) {
// Is it a private method call?
// TODO r$ check here because we use invokespecial to avoid virtual dispatch on field changes...
if (opcode == INVOKESPECIAL && name.charAt(0) != '<' && !name.startsWith("r$")) {
@@ -134,7 +135,7 @@ class MethodCopier extends MethodVisitor implements Constants {
// private method call
// leaving the invokespecial alone will cause a verify error
String descriptor = Utils.insertExtraParameter(owner, desc);
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, descriptor);
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, descriptor, false);
return;
} else {
// super call
@@ -146,9 +147,9 @@ class MethodCopier extends MethodVisitor implements Constants {
MethodMember target = supertypeDescriptor.getByNameAndDescriptor(name+desc);
if (target!=null && target.isProtected()) {
// A null target means that method is not in the supertype, so didn't get a superdispatcher
super.visitMethodInsn(INVOKESPECIAL,classname,name+methodSuffixSuperDispatcher,desc);
super.visitMethodInsn(INVOKESPECIAL,classname,name+methodSuffixSuperDispatcher,desc, false);
} else {
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
return;
}
@@ -158,12 +159,12 @@ class MethodCopier extends MethodVisitor implements Constants {
if (opcode == INVOKESTATIC) {
MethodMember mm = typeDescriptor.getByDescriptor(name, desc);
if (mm != null && mm.isPrivate()) {
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, desc);
super.visitMethodInsn(INVOKESTATIC, Utils.getExecutorName(classname, suffix), name, desc, false);
done = true;
}
}
if (!done) {
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}

View File

@@ -818,7 +818,7 @@ public class MethodInvokerRewriter {
// Make a call to check if this field operation must be intercepted:
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mInstanceFieldInterceptionRequired, "(ILjava/lang/String;)Z");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mInstanceFieldInterceptionRequired, "(ILjava/lang/String;)Z", false);
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1); // IF (false) GOTO l1
Utils.insertBoxInsns(mv, desc); // box the value if necessary
@@ -827,7 +827,7 @@ public class MethodInvokerRewriter {
// now stack is: FieldAccessor|newValue|target
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESPECIAL, owner, mInstanceFieldSetterName,
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)V");
"(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)V", false);
Label l2 = new Label();
mv.visitJumpInsn(GOTO, l2);
mv.visitLabel(l1); // Did not need intercepting, do what you were going to do:
@@ -847,13 +847,13 @@ public class MethodInvokerRewriter {
// intercepted
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mInstanceFieldInterceptionRequired, "(ILjava/lang/String;)Z");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mInstanceFieldInterceptionRequired, "(ILjava/lang/String;)Z", false);
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1); // IF (false) GOTO l1
mv.visitInsn(DUP);
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESPECIAL, owner, mInstanceFieldGetterName,
"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;");
"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", false);
if (desc.length() != 1) {
if (!desc.equals(jlObject)) {
mv.visitTypeInsn(CHECKCAST, toDescriptor(desc));
@@ -874,13 +874,13 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
// Make a call to check if this field operation must be intercepted:
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mStaticFieldInterceptionRequired, "(ILjava/lang/String;)Z");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mStaticFieldInterceptionRequired, "(ILjava/lang/String;)Z", false);
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1); // IF (false) GOTO l1
// top of heap will be the new value
Utils.insertBoxInsns(mv, desc);
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESTATIC, owner, mStaticFieldSetterName, "(Ljava/lang/Object;Ljava/lang/String;)V");
mv.visitMethodInsn(INVOKESTATIC, owner, mStaticFieldSetterName, "(Ljava/lang/Object;Ljava/lang/String;)V", false);
Label l2 = new Label();
mv.visitJumpInsn(GOTO, l2);
mv.visitLabel(l1);
@@ -893,12 +893,12 @@ public class MethodInvokerRewriter {
// Make a call to check if this field operation must be intercepted:
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mStaticFieldInterceptionRequired, "(ILjava/lang/String;)Z");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mStaticFieldInterceptionRequired, "(ILjava/lang/String;)Z", false);
Label l1 = new Label();
mv.visitJumpInsn(IFEQ, l1); // IF (false) GOTO l1
// top of heap will be the new value
mv.visitLdcInsn(name);
mv.visitMethodInsn(INVOKESTATIC, owner, mStaticFieldGetterName, "(Ljava/lang/String;)Ljava/lang/Object;");
mv.visitMethodInsn(INVOKESTATIC, owner, mStaticFieldGetterName, "(Ljava/lang/String;)Ljava/lang/Object;", false);
if (desc.length() != 1) {
if (!desc.equals(jlObject)) {
mv.visitTypeInsn(CHECKCAST, toDescriptor(desc));
@@ -1014,7 +1014,7 @@ public class MethodInvokerRewriter {
// do more hoop jumping.
// Check on reloading having happened
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeDynamicName, "()Ljava/lang/Object;");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeDynamicName, "()Ljava/lang/Object;", false);
// mv.visitInsn(DUP);
@@ -1029,10 +1029,10 @@ public class MethodInvokerRewriter {
// Method java/lang/invoke/MethodHandles.lookup:()Ljava/lang/invoke/MethodHandles$Lookup;
mv.visitLdcInsn(typeRegistry.getId());
mv.visitLdcInsn(classId);
mv.visitMethodInsn(INVOKESTATIC,"java/lang/invoke/MethodHandles","lookup","()Ljava/lang/invoke/MethodHandles$Lookup;");
mv.visitMethodInsn(INVOKESTATIC,"java/lang/invoke/MethodHandles","lookup","()Ljava/lang/invoke/MethodHandles$Lookup;", false);
mv.visitLdcInsn(name+desc); // Ljava/lang/String;
mv.visitLdcInsn(bsmReferenceId); // I
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mPerformInvokeDynamicName, "([Ljava/lang/Object;IILjava/lang/Object;Ljava/lang/String;I)Ljava/lang/Object;");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mPerformInvokeDynamicName, "([Ljava/lang/Object;IILjava/lang/Object;Ljava/lang/String;I)Ljava/lang/Object;", false);
Label gotolabel = new Label();
mv.visitJumpInsn(GOTO, gotolabel);
@@ -1049,7 +1049,7 @@ public class MethodInvokerRewriter {
}
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
if (GlobalConfiguration.interceptReflection && rewriteReflectiveCall(opcode, owner, name, desc)) {
return;
}
@@ -1057,7 +1057,7 @@ public class MethodInvokerRewriter {
unitializedObjectsCount--;
}
if (name.equals("$getCallSiteArray")) {
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
// TODO [cglib optimizations] could recognize things that dont
@@ -1069,7 +1069,7 @@ public class MethodInvokerRewriter {
boolean isReloadable = typeRegistry != null
&& (owner.equals(slashedclassname) ? thisClassIsReloadable : typeRegistry.isReloadableTypeName(owner));
if (!isReloadable) {
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
rewroteOtherKindOfOperation = true;
@@ -1078,13 +1078,13 @@ public class MethodInvokerRewriter {
// boolean isVoidReturn = returnType.isVoid();
int classId = typeRegistry.getTypeIdFor(owner, true);
if (opcode == INVOKESTATIC) {
rewriteINVOKESTATIC(opcode, owner, name, desc, hasParams, returnType, classId);
rewriteINVOKESTATIC(opcode, owner, name, desc, hasParams, returnType, classId, itf);
} else if (opcode == INVOKEINTERFACE) {
rewriteINVOKEINTERFACE(opcode, owner, name, desc, hasParams, returnType, classId);
rewriteINVOKEINTERFACE(opcode, owner, name, desc, hasParams, returnType, classId, itf);
} else if (opcode == INVOKEVIRTUAL) {
rewriteINVOKEVIRTUAL(opcode, owner, name, desc, hasParams, returnType, classId);
rewriteINVOKEVIRTUAL(opcode, owner, name, desc, hasParams, returnType, classId, itf);
} else if (opcode == INVOKESPECIAL) {
rewriteINVOKESPECIAL(opcode, owner, name, desc, hasParams, returnType, classId);
rewriteINVOKESPECIAL(opcode, owner, name, desc, hasParams, returnType, classId, itf);
} else {
Utils.logAndThrow(log, "Failed to rewrite instruction " + Utils.toOpcodeString(opcode) + " in method "
+ this.methodname);
@@ -1123,7 +1123,7 @@ public class MethodInvokerRewriter {
* Rewrite an INVOKESTATIC instruction.
*/
private void rewriteINVOKESTATIC(final int opcode, final String owner, final String name, final String desc,
boolean hasParams, ReturnType returnType, int classId) {
boolean hasParams, ReturnType returnType, int classId, boolean itf) {
// 1. call istcheck(classId|methodId,
// methodName+methodDescriptor)
// If it returns 'null' then nothing has changed and the code
@@ -1133,7 +1133,7 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(name + desc);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeStaticName,
"(ILjava/lang/String;)Ljava/lang/Object;");
"(ILjava/lang/String;)Ljava/lang/Object;", false);
// 2. preserve a copy of the return value (new target)
mv.visitInsn(DUP);
@@ -1168,7 +1168,7 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(name + desc);
// 7. calling __execute(params array,this,name+desc)
mv.visitMethodInsn(INVOKEINTERFACE, Utils.getInterfaceName(owner), mDynamicDispatchName, mDynamicDispatchDescriptor);
mv.visitMethodInsn(INVOKEINTERFACE, Utils.getInterfaceName(owner), mDynamicDispatchName, mDynamicDispatchDescriptor, true);
insertAppropriateReturn(returnType);
// 8. jump over the original call
@@ -1177,7 +1177,7 @@ public class MethodInvokerRewriter {
// 9. do what we were going to do
mv.visitLabel(l1);
mv.visitInsn(POP);
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
mv.visitLabel(gotolabel);
}
@@ -1207,11 +1207,11 @@ public class MethodInvokerRewriter {
*
*/
private void rewriteINVOKEINTERFACE(final int opcode, final String owner, final String name, final String desc,
boolean hasParams, ReturnType returnType, int classId) {
boolean hasParams, ReturnType returnType, int classId, final boolean itf) {
// 1. call 'boolean iicheck(classId|methodId, methodName+methodDescriptor)' to see if this needs interception
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(name + desc);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeInterfaceName, "(ILjava/lang/String;)Z");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeInterfaceName, "(ILjava/lang/String;)Z", false);
// 3. if false, do what was going to be done anyway
Label l1 = new Label();
@@ -1239,11 +1239,11 @@ public class MethodInvokerRewriter {
if (GlobalConfiguration.isJava18orHigher) {
// if the target is a generated lambda callsite object then calling __execute isn't going to work as those
// types don't have the method in them!
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, "iiIntercept", "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, "iiIntercept", "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;", false);
}
else {
// calling __execute(params array, this, name+desc)
mv.visitMethodInsn(INVOKEINTERFACE, owner, mDynamicDispatchName, mDynamicDispatchDescriptor);
mv.visitMethodInsn(INVOKEINTERFACE, owner, mDynamicDispatchName, mDynamicDispatchDescriptor, true);
}
insertAppropriateReturn(returnType);
@@ -1251,17 +1251,17 @@ public class MethodInvokerRewriter {
mv.visitJumpInsn(GOTO, gotolabel);
mv.visitLabel(l1);
// do what we were going to do:
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, true);
mv.visitLabel(gotolabel);
}
private void rewriteINVOKEVIRTUAL(final int opcode, final String owner, final String name, final String desc,
boolean hasParams, ReturnType returnType, int classId) {
boolean hasParams, ReturnType returnType, int classId, final boolean itf) {
// 1. call icheck(classId|methodId, methodName+methodDescriptor)
// to see if this needs interception
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(name + desc);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeVirtualName, "(ILjava/lang/String;)Z");
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeVirtualName, "(ILjava/lang/String;)Z", false);
// Return value is the extracted interface to call if there is a
// change and it can't be called directly
@@ -1299,7 +1299,7 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(name + desc);
// calling __execute(params array,this,name+desc)
mv.visitMethodInsn(INVOKEVIRTUAL, owner, mDynamicDispatchName, mDynamicDispatchDescriptor);
mv.visitMethodInsn(INVOKEVIRTUAL, owner, mDynamicDispatchName, mDynamicDispatchDescriptor, itf);
insertAppropriateReturn(returnType);
Label gotolabel = new Label();
@@ -1308,7 +1308,7 @@ public class MethodInvokerRewriter {
// 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);
super.visitMethodInsn(opcode, owner, name, desc, itf);
mv.visitLabel(gotolabel);
}
@@ -1320,14 +1320,14 @@ public class MethodInvokerRewriter {
* package up our parameters and invoke it.
*/
private void rewriteINVOKESPECIAL(final int opcode, final String owner, final String name, final String desc,
boolean hasParams, ReturnType returnType, int classId) {
boolean hasParams, ReturnType returnType, int classId, final boolean itf) {
if (unitializedObjectsCount == -1 && name.charAt(0) == '<') {
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
if (!name.equals("<init>") && owner.equals(slashedclassname)) {
// being used to invoke a private method
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
// the executor builder will sort it out
return;
}
@@ -1336,7 +1336,7 @@ public class MethodInvokerRewriter {
// constructor
if (isEnum && isClinitOrEnumInit && fieldcount > GlobalConfiguration.enumLimit && owner.equals(slashedclassname)) {
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
@@ -1345,7 +1345,7 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(desc);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForConstructorName,
"(ILjava/lang/String;)Ljava/lang/Object;");
"(ILjava/lang/String;)Ljava/lang/Object;", false);
mv.visitInsn(DUP);
// 3. Was it null?
@@ -1396,7 +1396,7 @@ public class MethodInvokerRewriter {
Utils.insertUnboxInsns(mv, 'I', true);
mv.visitInsn(ACONST_NULL);
mv.visitMethodInsn(INVOKESPECIAL, owner, "<init>", "(Ljava/lang/String;ILorg/springsource/loaded/C;)V");
mv.visitMethodInsn(INVOKESPECIAL, owner, "<init>", "(Ljava/lang/String;ILorg/springsource/loaded/C;)V", itf);
} else if (owner.contains("_closure")) { // TODO need more robust way to identify when target is a closure?
mv.visitInsn(SWAP); // now params array on top instance underneath
mv.visitInsn(DUP_X1); // give us an array instance to retrieve 1 from
@@ -1408,10 +1408,10 @@ public class MethodInvokerRewriter {
mv.visitInsn(AALOAD);
mv.visitInsn(ACONST_NULL);
mv.visitMethodInsn(INVOKESPECIAL, owner, "<init>",
"(Ljava/lang/Object;Ljava/lang/Object;Lorg/springsource/loaded/C;)V");
"(Ljava/lang/Object;Ljava/lang/Object;Lorg/springsource/loaded/C;)V", itf);
} else {
mv.visitInsn(ACONST_NULL);
mv.visitMethodInsn(INVOKESPECIAL, owner, "<init>", "(Lorg/springsource/loaded/C;)V");
mv.visitMethodInsn(INVOKESPECIAL, owner, "<init>", "(Lorg/springsource/loaded/C;)V", itf);
}
// stack is now an instance then the params
@@ -1428,7 +1428,7 @@ public class MethodInvokerRewriter {
// stack is now the two instances
mv.visitInsn(DUP);
mv.visitInsn(ACONST_NULL);
mv.visitMethodInsn(INVOKESPECIAL, owner, "<init>", "(Lorg/springsource/loaded/C;)V");
mv.visitMethodInsn(INVOKESPECIAL, owner, "<init>", "(Lorg/springsource/loaded/C;)V", itf);
// stack is now an instance
mv.visitVarInsn(ALOAD, max + 1);
// stack is now an instance then the dispatcher instance
@@ -1440,7 +1440,7 @@ public class MethodInvokerRewriter {
// stack is now the dispatcher instance, null, the instance and the name+desc!
}
mv.visitMethodInsn(INVOKEINTERFACE, "org/springsource/loaded/__DynamicallyDispatchable", mDynamicDispatchName,
mDynamicDispatchDescriptor);
mDynamicDispatchDescriptor, true);
mv.visitInsn(POP);
// mv.visitMethodInsn(INVOKESPECIAL, "ctors/Callee", "<init>", "()V");
@@ -1457,7 +1457,7 @@ public class MethodInvokerRewriter {
mv.visitJumpInsn(GOTO, gotolabel);
mv.visitLabel(l1);
mv.visitInsn(POP);
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
mv.visitLabel(gotolabel);
} else {
@@ -1466,7 +1466,7 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(Utils.toCombined(typeRegistry.getId(), classId));
mv.visitLdcInsn(name + desc);
mv.visitMethodInsn(INVOKESTATIC, tRegistryType, mChangedForInvokeSpecialName,
descriptorChangedForInvokeSpecialName);
descriptorChangedForInvokeSpecialName, false);
// Return value is the dispatcher instance to call if there is a
// change such that it can't be called directly - the method we called
@@ -1506,14 +1506,14 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(name + desc);
mv.visitMethodInsn(INVOKEINTERFACE, "org/springsource/loaded/__DynamicallyDispatchable", mDynamicDispatchName,
mDynamicDispatchDescriptor);
mDynamicDispatchDescriptor, true);
insertAppropriateReturn(returnType);
Label gotolabel = new Label();
mv.visitJumpInsn(GOTO, gotolabel);
mv.visitLabel(l1);
mv.visitInsn(POP);
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
mv.visitLabel(gotolabel);
}
}

View File

@@ -101,14 +101,14 @@ public class SystemClassReflectionInvestigator {
}
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
if (!GlobalConfiguration.interceptReflection || rewriteReflectiveCall(opcode, owner, name, desc)) {
return;
}
if (opcode == INVOKESPECIAL) {
unitializedObjectsCount--;
}
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
/**

View File

@@ -269,7 +269,7 @@ public class SystemClassReflectionRewriter {
}
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
if (!GlobalConfiguration.interceptReflection || rewriteReflectiveCall(opcode, owner, name, desc)) {
return;
}
@@ -309,7 +309,7 @@ public class SystemClassReflectionRewriter {
////// }
// }
// }
super.visitMethodInsn(opcode, owner, name, desc);
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
/**
@@ -338,57 +338,57 @@ public class SystemClassReflectionRewriter {
if (name.equals("getDeclaredFields")) {
// stack on arrival: <Class instance>
bits |= JLC_GETDECLAREDFIELDS;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdfs, jlcgdfsDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdfs, jlcgdfsDescriptor, false);
return true;
} else if (name.equals("getDeclaredField")) {
// stack on arrival: <Class instance> <String fieldname>
bits |= JLC_GETDECLAREDFIELD;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdf, jlcgdfDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdf, jlcgdfDescriptor, false);
return true;
} else if (name.equals("getField")) {
// stack on arrival: <Class instance> <String fieldname>
bits |= JLC_GETFIELD;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgf, jlcgfDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgf, jlcgfDescriptor, false);
return true;
} else if (name.equals("getDeclaredMethods")) {
// stack on arrival: <Class instance>
bits |= JLC_GETDECLAREDMETHODS;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdms, jlcgdmsDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdms, jlcgdmsDescriptor, false);
return true;
} else if (name.equals("getDeclaredMethod")) {
// stack on arrival: <Class instance> <String methodname> <Class[] paramTypes>
bits |= JLC_GETDECLAREDMETHOD;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdm, jlcgdmDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdm, jlcgdmDescriptor, false);
return true;
} else if (name.equals("getMethod")) {
// stack on arrival: <Class instance> <String methodname> <Class[] paramTypes>
bits |= JLC_GETMETHOD;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgm, jlcgmDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgm, jlcgmDescriptor, false);
return true;
} else if (name.equals("getDeclaredConstructor")) {
// stack on arrival: <Class instance> <Class[] paramTypes>
bits |= JLC_GETDECLAREDCONSTRUCTOR;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdc, jlcgdcDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgdc, jlcgdcDescriptor, false);
return true;
} else if (name.equals("getDeclaredConstructors")) {
// stack on arrival: <Class instance>
bits |= JLC_GETDECLAREDCONSTRUCTORS;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcGetDeclaredConstructorsMember,jlcGetDeclaredConstructorsDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcGetDeclaredConstructorsMember,jlcGetDeclaredConstructorsDescriptor, false);
return true;
} else if (name.equals("getConstructor")) {
// stack on arrival: <Class instance> <Class[] paramTypes>
bits |= JLC_GETCONSTRUCTOR;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgc, jlcgcDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgc, jlcgcDescriptor, false);
return true;
} else if (name.equals("getModifiers")) {
// stack on arrival: <Class instance>
bits |= JLC_GETMODIFIERS;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgmods, jlcgmodsDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgmods, jlcgmodsDescriptor, false);
return true;
} else if (name.equals("getMethods")) {
// stack on arrival: <class instance>
bits |= JLC_GETMETHODS;
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgms, jlcgmsDescriptor);
mv.visitMethodInsn(INVOKESTATIC, classname, jlcgms, jlcgmsDescriptor, false);
return true;
} else if (name.equals("newInstance")) {
// TODO determine if this actually needs rewriting? Just catching in this if clause to avoid the message

View File

@@ -1019,8 +1019,8 @@ public class TypeRewriter implements Constants {
}
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
super.visitMethodInsn(opcode, owner, name, desc);
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
super.visitMethodInsn(opcode, owner, name, desc, itf);
if (opcode == INVOKESPECIAL) {
unitializedObjectsCount--;
}
@@ -1037,7 +1037,7 @@ public class TypeRewriter implements Constants {
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(Opcodes.GETSTATIC, slashedname, fReloadableTypeFieldName, lReloadableType);
mv.visitMethodInsn(INVOKESPECIAL, tInstanceStateManager, "<init>",
"(Ljava/lang/Object;Lorg/springsource/loaded/ReloadableType;)V");
"(Ljava/lang/Object;Lorg/springsource/loaded/ReloadableType;)V", false);
// mv.visitMethodInsn(INVOKESPECIAL, tInstanceStateManager, "<init>", "(Ljava/lang/Object;)V");
mv.visitFieldInsn(PUTFIELD, slashedname, fInstanceFieldsName, lInstanceStateManager);
mv.visitLabel(l1);

View File

@@ -88,8 +88,8 @@ public class CglibPluginCapturing extends ClassVisitor implements Constants {
* this type so that we can remember the generator used (and drive it again later when the related type is reloaded).
*/
@Override
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
super.visitMethodInsn(opcode, owner, name, desc);
public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
super.visitMethodInsn(opcode, owner, name, desc, itf);
if (name.equals("generate")) {
// Code that calls generate:
// ALOAD 0
@@ -101,7 +101,7 @@ public class CglibPluginCapturing extends ClassVisitor implements Constants {
"L"+prefix+"/cglib/core/GeneratorStrategy;");
mv.visitVarInsn(ALOAD, 0); // AbstractClassGenerator instance
mv.visitMethodInsn(INVOKESTATIC, "org/springsource/loaded/agent/CglibPluginCapturing", "record",
"(Ljava/lang/Object;Ljava/lang/Object;)V");//Lnet/sf/cglib/core/GeneratorStrategy;Lnet/sf/cglib/core/AbstractClassGenerator);");
"(Ljava/lang/Object;Ljava/lang/Object;)V", false);//Lnet/sf/cglib/core/GeneratorStrategy;Lnet/sf/cglib/core/AbstractClassGenerator);");
}
}

View File

@@ -72,7 +72,7 @@ public class ClassVisitingConstructorAppender extends ClassVisitor implements Co
public void visitInsn(int opcode) {
if (opcode == RETURN) {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESTATIC, calleeOwner, calleeName, "(Ljava/lang/Object;)V");
mv.visitMethodInsn(INVOKESTATIC, calleeOwner, calleeName, "(Ljava/lang/Object;)V", false);
}
super.visitInsn(opcode);
}

View File

@@ -61,7 +61,7 @@ public class ModifyDefineInClassLoaderForClassArtifactsType extends ClassVisitor
mv.visitVarInsn(ALOAD, 1); // String name
mv.visitVarInsn(ALOAD, 2); // byte[] bytes
mv.visitMethodInsn(INVOKESTATIC, "org/springsource/loaded/agent/ModifyDefineInClassLoaderForClassArtifactsType",
"modify", "(Ljava/lang/ClassLoader;Ljava/lang/String;[B)[B");
"modify", "(Ljava/lang/ClassLoader;Ljava/lang/String;[B)[B", false);
mv.visitVarInsn(ASTORE, 2);
}

View File

@@ -127,6 +127,10 @@ public class EmptyCtor extends ClassVisitor implements Constants {
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
}
public void visitMethodInsn(int opcode, String owner, String name,
String desc, boolean itf) {
}
public void visitJumpInsn(int opcode, Label label) {
}
@@ -164,7 +168,7 @@ public class EmptyCtor extends ClassVisitor implements Constants {
public void visitEnd() {
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
}

View File

@@ -64,7 +64,8 @@ public class MethodPrinter extends MethodVisitor implements Opcodes {
return "#"+bsm.getTag()+" "+bsm.getOwner()+"."+bsm.getName()+bsm.getDesc();
}
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
// TODO include 'itf' flag in output (maybe only if true)
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (opcode == Opcodes.INVOKESTATIC) {
to.println(" INVOKESTATIC " + owner + "." + name + desc);
} else if (opcode == Opcodes.INVOKESPECIAL) {

View File

@@ -92,6 +92,7 @@ public class ReloadingJVM {
System.out.println("java.home="+System.getProperty("java.home"));
}
process = Runtime.getRuntime().exec(
// Run on my Java6
// "/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home"+
System.getProperty("java.home")+
"/bin/java -noverify -javaagent:" + agentJarLocation + " -cp " + javaclasspath + " " + AGENT_OPTION_STRING +

View File

@@ -98,7 +98,7 @@ public class FakeMethodVisitor extends MethodVisitor implements Constants {
public void visitMaxs(int maxStack, int maxLocals) {
}
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
events.append("visitMethodInsn(" + Utils.toOpcodeString(opcode) + "," + owner + "," + name + "," + desc + ") ");
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J180_b128"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -1,11 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
org.eclipse.jdt.core.compiler.source=1.8

2
testdata/.classpath vendored
View File

@@ -5,6 +5,6 @@
<classpathentry kind="lib" path="lib/cglib-nodep-2.2.jar"/>
<classpathentry kind="lib" path="/springloaded/lib/asm-3.2.jar"/>
<classpathentry kind="lib" path="/springloaded/lib/asm-tree-3.2.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/1.6.0_65"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -1,13 +1,11 @@
#
#Wed Jan 22 08:50:23 PST 2014
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -0,0 +1,5 @@
package github10;
public class Code {
}

View File

@@ -159,6 +159,9 @@ public class Serialize {
}
}
// java.io.InvalidClassException: remote.Person; local class incompatible: //
// stream classdesc serialVersionUID = 1687514539110537173,
// local class serialVersionUID = 510407729579040532
public static Object read(byte[] bs) {
try {
ByteArrayInputStream bais = new ByteArrayInputStream(bs);