renamed j8code to springloaded-java8

This commit is contained in:
Andy Clement
2014-02-17 16:28:05 -08:00
parent 909fd20387
commit 0accdf0c13
6 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<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_BETA.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>springloaded-java8</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=disabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.4
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=warning
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
org.eclipse.jdt.core.compiler.source=1.3

Binary file not shown.

View File

@@ -0,0 +1,3 @@
The main springloaded codebase is not yet using Java8. The Java8 'stuff' is captured here in this
project and included in the distributed agent. It should only be loaded if we find ourselves on a
Java8 VM. This code is not using Java8 source constructs, it is calling Java8 APIs.

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2014 Pivotal Software Inc. and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springsource.loaded.support;
import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Type;
/**
* This class encapsulates dependencies on Java 8 APIs (e.g. LambdaMetafactory).
*
* @author Andy Clement
* @since 1.2
*/
public class Java8 {
/**
* Notes:
*
* Useful to have an example of how this code behaves. Here is a bit of code:
*
* class basic.LambdaA {
* interface Foo { int m(); }
* static int run() {
* Foo f = null;
* f = () -> 77;
* return f.m();
* }
* }
*
* Here is a bootstrap method entry in the constant pool:
*
* 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
*
* At the invokedynamic site:
* bsmId = 0
* nameAndDescriptor = m()Lbasic/LambdaA$Foo;
*
* When invoking the metafactory bootstrap method the first two parameters are stacked by the VM automatically, namely the MethodHandles$Lookup
* instance (caller) and the first String (invokedName). What the VM actually sees is this:
*
* metaFactory parameters:
* 0:MethodHandles$Lookup caller = basic.LambdaA
* 1:String invokedName = "m"
* 2:MethodType invokedType = "()Foo"
* 3:MethodType samMethodType = "()int"
* 4:MethodHandle implMethod = (actually a DirectMethodHandle where memberName is "basic.LambdaA.lambda$run$0()int/invokeStatic")
* 5:MethodType instantiatedMethodType = "()int"
*
* With all that information then the calls in this case are relatively straightforward:
* CallSite callsite = LambdaMetafactory.metafactory(caller, invokedName, invokedType, samMethodType, implMethod, instantiatedMethodType);
* callsite.dynamicInvoker().invokeWithArguments((Object[])null);
*/
/**
* Programmatic emulation of INVOKEDYNAMIC so initialize the callsite via use of the bootstrap method then
* invoke the result.
*
* @param executorClass null if not yet reloaded
* @param handle
* @param bsmArgs
* @param lookup
* @return
*/
public static Object emulateInvokeDynamic(Class executorClass, Handle handle, Object[] bsmArgs, Object lookup, String indyNameAndDescriptor, Object[] indyParams) {
try {
CallSite callsite = callLambdaMetaFactory(bsmArgs,lookup,indyNameAndDescriptor,executorClass);
return callsite.dynamicInvoker().invokeWithArguments(indyParams);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
// TODO [perf] How about a table of CallSites indexed by invokedynamic number through the class file. Computed on first reference but cleared on reload. Possibly extend this to all invoke types!
// TODO [lambda] Need to handle altMetaFactory which is used when the lambdas are more 'complex' (e.g. Serializable)
public static CallSite callLambdaMetaFactory(Object[] bsmArgs, Object lookup, String indyNameAndDescriptor,Class executorClass) throws Exception {
MethodHandles.Lookup caller = (MethodHandles.Lookup)lookup;
ClassLoader callerLoader = caller.lookupClass().getClassLoader();
int descriptorStart = indyNameAndDescriptor.indexOf('(');
String invokedName = indyNameAndDescriptor.substring(0,descriptorStart);
MethodType invokedType = MethodType.fromMethodDescriptorString(indyNameAndDescriptor.substring(descriptorStart), callerLoader);
// Use bsmArgs to build the parameters
MethodType samMethodType = MethodType.fromMethodDescriptorString((String)(((Type)bsmArgs[0]).getDescriptor()), callerLoader);
Handle bsmArgsHandle = (Handle)bsmArgs[1];
String owner = bsmArgsHandle.getOwner();
String name = bsmArgsHandle.getName();
String descriptor = bsmArgsHandle.getDesc();
MethodType implMethodType = MethodType.fromMethodDescriptorString(descriptor, callerLoader);
// Looking up the lambda$run method in the caller class (note the caller class is the executor, which gets us around the
// problem of having to hack into LambdaMetafactory to intercept reflection)
MethodHandle implMethod = null;
// TODO [lambda] need to handle invokevirtual, surely
switch (bsmArgsHandle.getTag()) {
case 6: // INVOKESSTATIC
implMethod = caller.findStatic(caller.lookupClass(), name, implMethodType);
break;
case 7: // INVOKESPECIAL
// If there is an executor, the lambda function is actually modified from 'private instance' to 'public static' so adjust lookup:
if (executorClass == null) {
implMethod = caller.findSpecial(caller.lookupClass(), name, implMethodType, caller.lookupClass());
}
else {
implMethod = caller.findStatic(caller.lookupClass(), name, MethodType.fromMethodDescriptorString("(L"+owner+";"+descriptor.substring(1),callerLoader));
}
break;
default:
throw new IllegalStateException("nyi "+bsmArgsHandle.getTag());
}
MethodType instantiatedMethodType = MethodType.fromMethodDescriptorString((String)(((Type)bsmArgs[2]).getDescriptor()), callerLoader);
return LambdaMetafactory.metafactory(caller, invokedName, invokedType, samMethodType, implMethod, instantiatedMethodType);
}
}