Allow changing of lambda SAM types (alter method descriptor)

This is currently the 'slow' implementation and actually
slows down invokeinterface too - need to get the fast version
done...
This commit is contained in:
Andy Clement
2014-02-21 09:15:27 -08:00
parent e400e2da63
commit ad6a825688
9 changed files with 147 additions and 2 deletions

View File

@@ -362,4 +362,16 @@ public class GlobalConfiguration {
}
debugplugins = debugPlugins;
}
public final static boolean isJava18orHigher;
static {
String version = System.getProperty("java.version");
if (version.startsWith("1.8")) {
isJava18orHigher = true;
}
else {
isJava18orHigher = false;
}
}
}

View File

@@ -1236,8 +1236,15 @@ public class MethodInvokerRewriter {
mv.visitLdcInsn(name + desc); // [targetInstance paramArray targetInstance nameAndDescriptor]
// calling __execute(params array, this, name+desc)
mv.visitMethodInsn(INVOKEINTERFACE, owner, mDynamicDispatchName, mDynamicDispatchDescriptor);
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;");
}
else {
// calling __execute(params array, this, name+desc)
mv.visitMethodInsn(INVOKEINTERFACE, owner, mDynamicDispatchName, mDynamicDispatchDescriptor);
}
insertAppropriateReturn(returnType);
Label gotolabel = new Label();

View File

@@ -1259,6 +1259,33 @@ public class TypeRegistry {
return null; // let it fail anyway
}
/**
* See notes.md#001
*
*/
public static Object iiIntercept(Object instance, Object[] params, Object instance2, String nameAndDescriptor) {
Class<?> clazz= instance.getClass();
try {
if (clazz.getName().contains("$$Lambda")) {
// There will only be one method, the SAM method
Method[] ms = instance.getClass().getDeclaredMethods();
Method m = ms[0];
m.setAccessible(true);
Object o = m.invoke(instance, params);
return o;
}
else {
// Do what you were going to do...
Method m = instance.getClass().getDeclaredMethod("__execute",Object[].class,Object.class,String.class);
m.setAccessible(true);
return m.invoke(instance, params, instance, nameAndDescriptor);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@UsedByGeneratedCode
public static __DynamicallyDispatchable ispcheck(int ids, String nameAndDescriptor) {
if (GlobalConfiguration.isRuntimeLogging && log.isLoggable(Level.FINER)) {

View File

@@ -41,6 +41,7 @@ import org.springsource.loaded.TypeRegistry;
import org.springsource.loaded.Utils;
import org.springsource.loaded.SystemClassReflectionRewriter.RewriteResult;
import org.springsource.loaded.ri.ReflectiveInterceptor;
import org.springsource.loaded.support.Java8;
/**
* The entry point for the agent - all classes that can be modified will be passed into preProcess(). They have to be dealt with in
@@ -148,6 +149,10 @@ public class SpringLoadedPreProcessor implements Constants {
// return rr.bytes;
// }
}
else if (slashedClassName.equals("java/lang/invoke/InnerClassLambdaMetafactory")) {
bytes = Java8.enhanceInnerClassLambdaMetaFactory(bytes);
return bytes;
}
}
return bytes;
}

View File

@@ -140,4 +140,15 @@ public class Java8 {
return LambdaMetafactory.metafactory(caller, invokedName, invokedType, samMethodType, implMethod, instantiatedMethodType);
}
/**
* The metafactory we are enhancing is responsible for generating the anonymous classes that will call the lambda methods in our type
*
* @param bytes
* @return
*/
public static byte[] enhanceInnerClassLambdaMetaFactory(byte[] bytes) {
// TODO Auto-generated method stub
return null;
}
}