Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
2e5b7b7f
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2e5b7b7f
编写于
6月 19, 2013
作者:
C
chegar
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8017044: anti-delta fix for 8015402
Reviewed-by: alanb
上级
0a85f8ea
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
246 addition
and
219 deletion
+246
-219
src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
...java/lang/invoke/AbstractValidatingLambdaMetafactory.java
+130
-49
src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
...classes/java/lang/invoke/InnerClassLambdaMetafactory.java
+69
-73
src/share/classes/java/lang/invoke/LambdaMetafactory.java
src/share/classes/java/lang/invoke/LambdaMetafactory.java
+47
-97
未找到文件。
src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
浏览文件 @
2e5b7b7f
...
...
@@ -24,11 +24,14 @@
*/
package
java.lang.invoke
;
import
java.io.Serializable
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
sun.invoke.util.Wrapper
;
import
static
sun
.
invoke
.
util
.
Wrapper
.
forPrimitiveType
;
import
static
sun
.
invoke
.
util
.
Wrapper
.
forWrapperType
;
import
static
sun
.
invoke
.
util
.
Wrapper
.
isWrapperType
;
import
static
sun
.
invoke
.
util
.
Wrapper
.*;
/**
* Abstract implementation of a lambda metafactory which provides parameter unrolling and input validation.
...
...
@@ -64,52 +67,34 @@ import static sun.invoke.util.Wrapper.isWrapperType;
final
MethodType
instantiatedMethodType
;
// Instantiated erased functional interface method type "(Integer)Object"
final
boolean
isSerializable
;
// Should the returned instance be serializable
final
Class
<?>[]
markerInterfaces
;
// Additional marker interfaces to be implemented
final
MethodType
[]
additionalBridges
;
// Signatures of additional methods to bridge
/**
* Meta-factory constructor.
*
* @param caller Stacked automatically by VM; represents a lookup context
* with the accessibility privileges of the caller.
* @param invokedType Stacked automatically by VM; the signature of the
* invoked method, which includes the expected static
* type of the returned lambda object, and the static
* types of the captured arguments for the lambda. In
* the event that the implementation method is an
* instance method, the first argument in the invocation
* signature will correspond to the receiver.
* @param samMethod The primary method in the functional interface to which
* the lambda or method reference is being converted,
* represented as a method handle.
* @param implMethod The implementation method which should be called
* (with suitable adaptation of argument types, return
* types, and adjustment for captured arguments) when
* methods of the resulting functional interface instance
* are invoked.
* @param instantiatedMethodType The signature of the primary functional
* interface method after type variables are
* substituted with their instantiation from
* the capture site
* @param isSerializable Should the lambda be made serializable? If set,
* either the target type or one of the additional SAM
* types must extend {@code Serializable}.
* @param markerInterfaces Additional interfaces which the lambda object
* should implement.
* @param additionalBridges Method types for additional signatures to be
* bridged to the implementation method
* @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
* of the caller.
* @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
* expected static type of the returned lambda object, and the static types of the captured
* arguments for the lambda. In the event that the implementation method is an instance method,
* the first argument in the invocation signature will correspond to the receiver.
* @param samMethod The primary method in the functional interface to which the lambda or method reference is
* being converted, represented as a method handle.
* @param implMethod The implementation method which should be called (with suitable adaptation of argument
* types, return types, and adjustment for captured arguments) when methods of the resulting
* functional interface instance are invoked.
* @param instantiatedMethodType The signature of the primary functional interface method after type variables
* are substituted with their instantiation from the capture site
* @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
* @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
AbstractValidatingLambdaMetafactory
(
MethodHandles
.
Lookup
caller
,
MethodType
invokedType
,
MethodHandle
samMethod
,
MethodHandle
implMethod
,
MethodType
instantiatedMethodType
,
boolean
isSerializable
,
Class
<?>[]
markerInterfaces
,
MethodType
[]
additionalBridges
)
int
flags
,
Class
<?>[]
markerInterfaces
)
throws
ReflectiveOperationException
,
LambdaConversionException
{
this
.
targetClass
=
caller
.
lookupClass
();
this
.
invokedType
=
invokedType
;
...
...
@@ -133,22 +118,32 @@ import static sun.invoke.util.Wrapper.isWrapperType;
implKind
==
MethodHandleInfo
.
REF_invokeInterface
;
this
.
implDefiningClass
=
implInfo
.
getDeclaringClass
();
this
.
implMethodType
=
implInfo
.
getMethodType
();
this
.
instantiatedMethodType
=
instantiatedMethodType
;
this
.
isSerializable
=
isSerializable
;
this
.
markerInterfaces
=
markerInterfaces
;
this
.
additionalBridges
=
additionalBridges
;
if
(!
samClass
.
isInterface
())
{
throw
new
LambdaConversionException
(
String
.
format
(
"Functional interface %s is not an interface"
,
samClass
.
getName
()));
"Functional interface %s is not an interface"
,
samClass
.
getName
()));
}
boolean
foundSerializableSupertype
=
Serializable
.
class
.
isAssignableFrom
(
samBase
);
for
(
Class
<?>
c
:
markerInterfaces
)
{
if
(!
c
.
isInterface
())
{
throw
new
LambdaConversionException
(
String
.
format
(
"Marker interface %s is not an interface"
,
c
.
getName
()));
"Marker interface %s is not an interface"
,
c
.
getName
()));
}
foundSerializableSupertype
|=
Serializable
.
class
.
isAssignableFrom
(
c
);
}
this
.
isSerializable
=
((
flags
&
LambdaMetafactory
.
FLAG_SERIALIZABLE
)
!=
0
)
||
foundSerializableSupertype
;
if
(
isSerializable
&&
!
foundSerializableSupertype
)
{
markerInterfaces
=
Arrays
.
copyOf
(
markerInterfaces
,
markerInterfaces
.
length
+
1
);
markerInterfaces
[
markerInterfaces
.
length
-
1
]
=
Serializable
.
class
;
}
this
.
markerInterfaces
=
markerInterfaces
;
}
/**
...
...
@@ -270,9 +265,9 @@ import static sun.invoke.util.Wrapper.isWrapperType;
}
/**
* Check type adaptability
for parameter types.
* @param fromType
Type to convert from
* @param toType
Type to convert to
* Check type adaptability
* @param fromType
* @param toType
* @param strict If true, do strict checks, else allow that fromType may be parameterized
* @return True if 'fromType' can be passed to an argument of 'toType'
*/
...
...
@@ -304,14 +299,15 @@ import static sun.invoke.util.Wrapper.isWrapperType;
}
}
else
{
// both are reference types: fromType should be a superclass of toType.
return
!
strict
||
toType
.
isAssignableFrom
(
fromType
)
;
return
strict
?
toType
.
isAssignableFrom
(
fromType
)
:
true
;
}
}
}
/**
* Check type adaptability for return types -- special handling of void type)
* and parameterized fromType
* Check type adaptability for return types -- special handling of void type) and parameterized fromType
* @param fromType
* @param toType
* @return True if 'fromType' can be converted to 'toType'
*/
private
boolean
isAdaptableToAsReturn
(
Class
<?>
fromType
,
Class
<?>
toType
)
{
...
...
@@ -342,4 +338,89 @@ import static sun.invoke.util.Wrapper.isWrapperType;
}
***********************/
/**
* Find the functional interface method and corresponding abstract methods
* which should be bridged. The functional interface method and those to be
* bridged will have the same name and number of parameters. Check for
* matching default methods (non-abstract), the VM will create bridges for
* default methods; We don't have enough readily available type information
* to distinguish between where the functional interface method should be
* bridged and where the default method should be bridged; This situation is
* flagged.
*/
class
MethodAnalyzer
{
private
final
Method
[]
methods
=
samBase
.
getMethods
();
private
Method
samMethod
=
null
;
private
final
List
<
Method
>
methodsToBridge
=
new
ArrayList
<>(
methods
.
length
);
private
boolean
conflictFoundBetweenDefaultAndBridge
=
false
;
MethodAnalyzer
()
{
String
samMethodName
=
samInfo
.
getName
();
Class
<?>[]
samParamTypes
=
samMethodType
.
parameterArray
();
int
samParamLength
=
samParamTypes
.
length
;
Class
<?>
samReturnType
=
samMethodType
.
returnType
();
Class
<?>
objectClass
=
Object
.
class
;
List
<
Method
>
defaultMethods
=
new
ArrayList
<>(
methods
.
length
);
for
(
Method
m
:
methods
)
{
if
(
m
.
getName
().
equals
(
samMethodName
)
&&
m
.
getDeclaringClass
()
!=
objectClass
)
{
Class
<?>[]
mParamTypes
=
m
.
getParameterTypes
();
if
(
mParamTypes
.
length
==
samParamLength
)
{
// Method matches name and parameter length -- and is not Object
if
(
Modifier
.
isAbstract
(
m
.
getModifiers
()))
{
// Method is abstract
if
(
m
.
getReturnType
().
equals
(
samReturnType
)
&&
Arrays
.
equals
(
mParamTypes
,
samParamTypes
))
{
// Exact match, this is the SAM method signature
samMethod
=
m
;
}
else
if
(!
hasMatchingBridgeSignature
(
m
))
{
// Record bridges, exclude methods with duplicate signatures
methodsToBridge
.
add
(
m
);
}
}
else
{
// Record default methods for conflict testing
defaultMethods
.
add
(
m
);
}
}
}
}
for
(
Method
dm
:
defaultMethods
)
{
if
(
hasMatchingBridgeSignature
(
dm
))
{
conflictFoundBetweenDefaultAndBridge
=
true
;
break
;
}
}
}
Method
getSamMethod
()
{
return
samMethod
;
}
List
<
Method
>
getMethodsToBridge
()
{
return
methodsToBridge
;
}
boolean
conflictFoundBetweenDefaultAndBridge
()
{
return
conflictFoundBetweenDefaultAndBridge
;
}
/**
* Search the list of previously found bridge methods to determine if there is a method with the same signature
* (return and parameter types) as the specified method.
*
* @param m The method to match
* @return True if the method was found, False otherwise
*/
private
boolean
hasMatchingBridgeSignature
(
Method
m
)
{
Class
<?>[]
ptypes
=
m
.
getParameterTypes
();
Class
<?>
rtype
=
m
.
getReturnType
();
for
(
Method
md
:
methodsToBridge
)
{
if
(
md
.
getReturnType
().
equals
(
rtype
)
&&
Arrays
.
equals
(
ptypes
,
md
.
getParameterTypes
()))
{
return
true
;
}
}
return
false
;
}
}
}
src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
浏览文件 @
2e5b7b7f
...
...
@@ -25,16 +25,15 @@
package
java.lang.invoke
;
import
jdk.internal.org.objectweb.asm.*
;
import
sun.misc.Unsafe
;
import
java.lang.reflect.Constructor
;
import
java.security.AccessController
;
import
java.security.PrivilegedAction
;
import
java.lang.reflect.Method
;
import
java.security.ProtectionDomain
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
jdk.internal.org.objectweb.asm.*
;
import
static
jdk
.
internal
.
org
.
objectweb
.
asm
.
Opcodes
.*;
import
sun.misc.Unsafe
;
import
java.security.AccessController
;
import
java.security.PrivilegedAction
;
/**
* Lambda metafactory implementation which dynamically creates an inner-class-like class per lambda callsite.
...
...
@@ -42,8 +41,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* @see LambdaMetafactory
*/
/* package */
final
class
InnerClassLambdaMetafactory
extends
AbstractValidatingLambdaMetafactory
{
private
static
final
Unsafe
UNSAFE
=
Unsafe
.
getUnsafe
();
private
static
final
int
CLASSFILE_VERSION
=
51
;
private
static
final
String
METHOD_DESCRIPTOR_VOID
=
Type
.
getMethodDescriptor
(
Type
.
VOID_TYPE
);
private
static
final
String
NAME_MAGIC_ACCESSOR_IMPL
=
"java/lang/invoke/MagicLambdaImpl"
;
...
...
@@ -80,51 +77,36 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
private
final
Type
[]
instantiatedArgumentTypes
;
// ASM types for the functional interface arguments
/**
* General meta-factory constructor, supporting both standard cases and
* allowing for uncommon options such as serialization or bridging.
* General meta-factory constructor, standard cases and allowing for uncommon options such as serialization.
*
* @param caller Stacked automatically by VM; represents a lookup context
* with the accessibility privileges of the caller.
* @param invokedType Stacked automatically by VM; the signature of the
* invoked method, which includes the expected static
* type of the returned lambda object, and the static
* types of the captured arguments for the lambda. In
* the event that the implementation method is an
* instance method, the first argument in the invocation
* signature will correspond to the receiver.
* @param samMethod The primary method in the functional interface to which
* the lambda or method reference is being converted,
* represented as a method handle.
* @param implMethod The implementation method which should be called (with
* suitable adaptation of argument types, return types,
* and adjustment for captured arguments) when methods of
* the resulting functional interface instance are invoked.
* @param instantiatedMethodType The signature of the primary functional
* interface method after type variables are
* substituted with their instantiation from
* the capture site
* @param isSerializable Should the lambda be made serializable? If set,
* either the target type or one of the additional SAM
* types must extend {@code Serializable}.
* @param markerInterfaces Additional interfaces which the lambda object
* should implement.
* @param additionalBridges Method types for additional signatures to be
* bridged to the implementation method
* @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
* of the caller.
* @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
* expected static type of the returned lambda object, and the static types of the captured
* arguments for the lambda. In the event that the implementation method is an instance method,
* the first argument in the invocation signature will correspond to the receiver.
* @param samMethod The primary method in the functional interface to which the lambda or method reference is
* being converted, represented as a method handle.
* @param implMethod The implementation method which should be called (with suitable adaptation of argument
* types, return types, and adjustment for captured arguments) when methods of the resulting
* functional interface instance are invoked.
* @param instantiatedMethodType The signature of the primary functional interface method after type variables
* are substituted with their instantiation from the capture site
* @param flags A bitmask containing flags that may influence the translation of this lambda expression. Defined
* fields include FLAG_SERIALIZABLE.
* @param markerInterfaces Additional interfaces which the lambda object should implement.
* @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
* @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
public
InnerClassLambdaMetafactory
(
MethodHandles
.
Lookup
caller
,
MethodType
invokedType
,
MethodHandle
samMethod
,
MethodHandle
implMethod
,
MethodType
instantiatedMethodType
,
boolean
isSerializable
,
Class
<?>[]
markerInterfaces
,
MethodType
[]
additionalBridges
)
int
flags
,
Class
<?>[]
markerInterfaces
)
throws
ReflectiveOperationException
,
LambdaConversionException
{
super
(
caller
,
invokedType
,
samMethod
,
implMethod
,
instantiatedMethodType
,
isSerializable
,
markerInterfaces
,
additionalBridges
);
super
(
caller
,
invokedType
,
samMethod
,
implMethod
,
instantiatedMethodType
,
flags
,
markerInterfaces
);
implMethodClassName
=
implDefiningClass
.
getName
().
replace
(
'.'
,
'/'
);
implMethodName
=
implInfo
.
getName
();
implMethodDesc
=
implMethodType
.
toMethodDescriptorString
();
...
...
@@ -152,8 +134,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* @return a CallSite, which, when invoked, will return an instance of the
* functional interface
* @throws ReflectiveOperationException
* @throws LambdaConversionException If properly formed functional interface
* is not found
* @throws LambdaConversionException If properly formed functional interface is not found
*/
@Override
CallSite
buildCallSite
()
throws
ReflectiveOperationException
,
LambdaConversionException
{
...
...
@@ -193,16 +174,8 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* Generate a class file which implements the functional
* interface, define and return the class.
*
* @implNote The class that is generated does not include signature
* information for exceptions that may be present on the SAM method.
* This is to reduce classfile size, and is harmless as checked exceptions
* are erased anyway, no one will ever compile against this classfile,
* and we make no guarantees about the reflective properties of lambda
* objects.
*
* @return a Class which implements the functional interface
* @throws LambdaConversionException If properly formed functional interface
* is not found
* @throws LambdaConversionException If properly formed functional interface is not found
*/
private
Class
<?>
spinInnerClass
()
throws
LambdaConversionException
{
String
samName
=
samBase
.
getName
().
replace
(
'.'
,
'/'
);
...
...
@@ -224,22 +197,28 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
generateConstructor
();
MethodAnalyzer
ma
=
new
MethodAnalyzer
();
// Forward the SAM method
String
methodDescriptor
=
samMethodType
.
toMethodDescriptorString
();
MethodVisitor
mv
=
cw
.
visitMethod
(
ACC_PUBLIC
,
samInfo
.
getName
(),
methodDescriptor
,
null
,
null
);
new
ForwardingMethodGenerator
(
mv
).
generate
(
methodDescriptor
);
if
(
ma
.
getSamMethod
()
==
null
)
{
throw
new
LambdaConversionException
(
String
.
format
(
"Functional interface method not found: %s"
,
samMethodType
));
}
else
{
generateForwardingMethod
(
ma
.
getSamMethod
(),
false
);
}
// Forward the bridges
if
(
additionalBridges
!=
null
)
{
for
(
MethodType
mt
:
additionalBridges
)
{
methodDescriptor
=
mt
.
toMethodDescriptorString
();
mv
=
cw
.
visitMethod
(
ACC_PUBLIC
|
ACC_BRIDGE
,
samInfo
.
getName
(),
methodDescriptor
,
null
,
null
);
new
ForwardingMethodGenerator
(
mv
).
generate
(
methodDescriptor
);
// @@@ The commented-out code is temporary, pending the VM's ability to bridge all methods on request
// @@@ Once the VM can do fail-over, uncomment the !ma.wasDefaultMethodFound() test, and emit the appropriate
// @@@ classfile attribute to request custom bridging. See 8002092.
if
(!
ma
.
getMethodsToBridge
().
isEmpty
()
/* && !ma.conflictFoundBetweenDefaultAndBridge() */
)
{
for
(
Method
m
:
ma
.
getMethodsToBridge
())
{
generateForwardingMethod
(
m
,
true
);
}
}
if
(
isSerializable
)
if
(
isSerializable
)
{
generateWriteReplace
();
}
cw
.
visitEnd
();
...
...
@@ -268,8 +247,8 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
}
);
return
UNSAFE
.
defineClass
(
lambdaClassName
,
classBytes
,
0
,
classBytes
.
length
,
loader
,
pd
);
return
(
Class
<?>)
Unsafe
.
getUnsafe
()
.
defineClass
(
lambdaClassName
,
classBytes
,
0
,
classBytes
.
length
,
loader
,
pd
);
}
/**
...
...
@@ -286,8 +265,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
ctor
.
visitVarInsn
(
ALOAD
,
0
);
ctor
.
visitVarInsn
(
argTypes
[
i
].
getOpcode
(
ILOAD
),
lvIndex
+
1
);
lvIndex
+=
argTypes
[
i
].
getSize
();
ctor
.
visitFieldInsn
(
PUTFIELD
,
lambdaClassName
,
argNames
[
i
],
argTypes
[
i
].
getDescriptor
());
ctor
.
visitFieldInsn
(
PUTFIELD
,
lambdaClassName
,
argNames
[
i
],
argTypes
[
i
].
getDescriptor
());
}
ctor
.
visitInsn
(
RETURN
);
ctor
.
visitMaxs
(-
1
,
-
1
);
// Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
...
...
@@ -305,7 +283,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
mv
.
visitCode
();
mv
.
visitTypeInsn
(
NEW
,
NAME_SERIALIZED_LAMBDA
);
mv
.
visitInsn
(
DUP
);
mv
.
visitInsn
(
DUP
);
;
mv
.
visitLdcInsn
(
Type
.
getType
(
targetClass
));
mv
.
visitLdcInsn
(
samInfo
.
getReferenceKind
());
mv
.
visitLdcInsn
(
invokedType
.
returnType
().
getName
().
replace
(
'.'
,
'/'
));
...
...
@@ -334,6 +312,24 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
mv
.
visitEnd
();
}
/**
* Generate a method which calls the lambda implementation method,
* converting arguments, as needed.
* @param m The method whose signature should be generated
* @param isBridge True if this methods should be flagged as a bridge
*/
private
void
generateForwardingMethod
(
Method
m
,
boolean
isBridge
)
{
Class
<?>[]
exceptionTypes
=
m
.
getExceptionTypes
();
String
[]
exceptionNames
=
new
String
[
exceptionTypes
.
length
];
for
(
int
i
=
0
;
i
<
exceptionTypes
.
length
;
i
++)
{
exceptionNames
[
i
]
=
exceptionTypes
[
i
].
getName
().
replace
(
'.'
,
'/'
);
}
String
methodDescriptor
=
Type
.
getMethodDescriptor
(
m
);
int
access
=
isBridge
?
ACC_PUBLIC
|
ACC_BRIDGE
:
ACC_PUBLIC
;
MethodVisitor
mv
=
cw
.
visitMethod
(
access
,
m
.
getName
(),
methodDescriptor
,
null
,
exceptionNames
);
new
ForwardingMethodGenerator
(
mv
).
generate
(
m
);
}
/**
* This class generates a method body which calls the lambda implementation
* method, converting arguments, as needed.
...
...
@@ -344,26 +340,26 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
super
(
mv
);
}
void
generate
(
String
methodDescriptor
)
{
void
generate
(
Method
m
)
throws
InternalError
{
visitCode
();
if
(
implKind
==
MethodHandleInfo
.
REF_newInvokeSpecial
)
{
visitTypeInsn
(
NEW
,
implMethodClassName
);
visitInsn
(
DUP
);
visitInsn
(
DUP
);
;
}
for
(
int
i
=
0
;
i
<
argTypes
.
length
;
i
++)
{
visitVarInsn
(
ALOAD
,
0
);
visitFieldInsn
(
GETFIELD
,
lambdaClassName
,
argNames
[
i
],
argTypes
[
i
].
getDescriptor
());
}
convertArgumentTypes
(
Type
.
getArgumentTypes
(
m
ethodDescriptor
));
convertArgumentTypes
(
Type
.
getArgumentTypes
(
m
));
// Invoke the method we want to forward to
visitMethodInsn
(
invocationOpcode
(),
implMethodClassName
,
implMethodName
,
implMethodDesc
);
// Convert the return value (if any) and return it
// Note: if adapting from non-void to void, the 'return' instruction will pop the unneeded result
Type
samReturnType
=
Type
.
getReturnType
(
m
ethodDescriptor
);
Type
samReturnType
=
Type
.
getReturnType
(
m
);
convertType
(
implMethodReturnType
,
samReturnType
,
samReturnType
);
visitInsn
(
samReturnType
.
getOpcode
(
Opcodes
.
IRETURN
));
...
...
src/share/classes/java/lang/invoke/LambdaMetafactory.java
浏览文件 @
2e5b7b7f
...
...
@@ -25,9 +25,6 @@
package
java.lang.invoke
;
import
java.io.Serializable
;
import
java.util.Arrays
;
/**
* <p>Bootstrap methods for converting lambda expressions and method references to functional interface objects.</p>
*
...
...
@@ -47,11 +44,16 @@ import java.util.Arrays;
*
* <p>When parameterized types are used, the instantiated type of the functional interface method may be different
* from that in the functional interface. For example, consider
*
{@code interface I<T> { int m(T x); }}
if this functional interface type is used in a lambda
*
{@code I<Byte>; v = ...}
, we need both the actual functional interface method which has the signature
*
{@code (Object)int}
and the erased instantiated type of the functional interface method (or simply
*
<code>interface I<T> { int m(T x); }</code>
if this functional interface type is used in a lambda
*
<code>I<Byte> v = ...</code>
, we need both the actual functional interface method which has the signature
*
<code>(Object)int</code>
and the erased instantiated type of the functional interface method (or simply
* <I>instantiated method type</I>), which has signature
* {@code (Byte)int}.
* <code>(Byte)int</code>.
*
* <p>While functional interfaces only have a single abstract method from the language perspective (concrete
* methods in Object are and default methods may be present), at the bytecode level they may actually have multiple
* methods because of the need for bridge methods. Invoking any of these methods on the lambda object will result
* in invoking the implementation method.
*
* <p>The argument list of the implementation method and the argument list of the functional interface method(s)
* may differ in several ways. The implementation methods may have additional arguments to accommodate arguments
...
...
@@ -142,59 +144,38 @@ import java.util.Arrays;
*/
public
class
LambdaMetafactory
{
/** Flag for alternate metafactories indicating the lambda object is
* must to be serializable */
/** Flag for alternate metafactories indicating the lambda object is must to be serializable */
public
static
final
int
FLAG_SERIALIZABLE
=
1
<<
0
;
/**
* Flag for alternate metafactories indicating the lambda object implements
* other marker interfaces
* Flag for alternate metafactories indicating the lambda object implements other marker interfaces
* besides Serializable
*/
public
static
final
int
FLAG_MARKERS
=
1
<<
1
;
/**
* Flag for alternate metafactories indicating the lambda object requires
* additional bridge methods
*/
public
static
final
int
FLAG_BRIDGES
=
1
<<
2
;
private
static
final
Class
<?>[]
EMPTY_CLASS_ARRAY
=
new
Class
<?>[
0
];
private
static
final
MethodType
[]
EMPTY_MT_ARRAY
=
new
MethodType
[
0
];
/**
* Standard meta-factory for conversion of lambda expressions or method
* references to functional interfaces.
/**
* Standard meta-factory for conversion of lambda expressions or method references to functional interfaces.
*
* @param caller Stacked automatically by VM; represents a lookup context
* with the accessibility privileges of the caller.
* @param invokedName Stacked automatically by VM; the name of the invoked
* method as it appears at the call site.
* @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
* of the caller.
* @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
* Currently unused.
* @param invokedType Stacked automatically by VM; the signature of the
* invoked method, which includes the expected static
* type of the returned lambda object, and the static
* types of the captured arguments for the lambda.
* In the event that the implementation method is an
* instance method, the first argument in the invocation
* signature will correspond to the receiver.
* @param samMethod The primary method in the functional interface to which
* the lambda or method reference is being converted,
* represented as a method handle.
* @param implMethod The implementation method which should be called
* (with suitable adaptation of argument types, return
* types, and adjustment for captured arguments) when
* methods of the resulting functional interface instance
* are invoked.
* @param instantiatedMethodType The signature of the primary functional
* interface method after type variables
* are substituted with their instantiation
* from the capture site
* @return a CallSite, which, when invoked, will return an instance of the
* functional interface
* @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
* expected static type of the returned lambda object, and the static types of the captured
* arguments for the lambda. In the event that the implementation method is an instance method,
* the first argument in the invocation signature will correspond to the receiver.
* @param samMethod The primary method in the functional interface to which the lambda or method reference is
* being converted, represented as a method handle.
* @param implMethod The implementation method which should be called (with suitable adaptation of argument
* types, return types, and adjustment for captured arguments) when methods of the resulting
* functional interface instance are invoked.
* @param instantiatedMethodType The signature of the primary functional interface method after type variables
* are substituted with their instantiation from the capture site
* @return a CallSite, which, when invoked, will return an instance of the functional interface
* @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
* @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
public
static
CallSite
metaFactory
(
MethodHandles
.
Lookup
caller
,
String
invokedName
,
...
...
@@ -204,17 +185,15 @@ public class LambdaMetafactory {
MethodType
instantiatedMethodType
)
throws
ReflectiveOperationException
,
LambdaConversionException
{
AbstractValidatingLambdaMetafactory
mf
;
mf
=
new
InnerClassLambdaMetafactory
(
caller
,
invokedType
,
samMethod
,
implMethod
,
instantiatedMethodType
,
false
,
EMPTY_CLASS_ARRAY
,
EMPTY_MT_ARRAY
);
mf
=
new
InnerClassLambdaMetafactory
(
caller
,
invokedType
,
samMethod
,
implMethod
,
instantiatedMethodType
,
0
,
EMPTY_CLASS_ARRAY
);
mf
.
validateMetafactoryArgs
();
return
mf
.
buildCallSite
();
}
/**
* Alternate meta-factory for conversion of lambda expressions or method
* references to functional interfaces, which supports serialization and
* other uncommon options.
* Alternate meta-factory for conversion of lambda expressions or method references to functional interfaces,
* which supports serialization and other uncommon options.
*
* The declared argument list for this method is:
*
...
...
@@ -234,28 +213,21 @@ public class LambdaMetafactory {
* int flags,
* int markerInterfaceCount, // IF flags has MARKERS set
* Class... markerInterfaces // IF flags has MARKERS set
* int bridgeCount, // IF flags has BRIDGES set
* MethodType... bridges // IF flags has BRIDGES set
* )
*
*
* @param caller Stacked automatically by VM; represents a lookup context
* with the accessibility privileges of the caller.
* @param invokedName Stacked automatically by VM; the name of the invoked
* method as it appears at the call site. Currently unused.
* @param invokedType Stacked automatically by VM; the signature of the
* invoked method, which includes the expected static
* type of the returned lambda object, and the static
* types of the captured arguments for the lambda.
* In the event that the implementation method is an
* instance method, the first argument in the invocation
* signature will correspond to the receiver.
* @param args flags and optional arguments, as described above
* @return a CallSite, which, when invoked, will return an instance of the
* functional interface
* @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
* of the caller.
* @param invokedName Stacked automatically by VM; the name of the invoked method as it appears at the call site.
* Currently unused.
* @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes thefu
* expected static type of the returned lambda object, and the static types of the captured
* arguments for the lambda. In the event that the implementation method is an instance method,
* the first argument in the invocation signature will correspond to the receiver.
* @param args argument to pass, flags, marker interface count, and marker interfaces as described above
* @return a CallSite, which, when invoked, will return an instance of the functional interface
* @throws ReflectiveOperationException
* @throws LambdaConversionException If any of the meta-factory protocol
* invariants are violated
* @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
*/
public
static
CallSite
altMetaFactory
(
MethodHandles
.
Lookup
caller
,
String
invokedName
,
...
...
@@ -267,7 +239,6 @@ public class LambdaMetafactory {
MethodType
instantiatedMethodType
=
(
MethodType
)
args
[
2
];
int
flags
=
(
Integer
)
args
[
3
];
Class
<?>[]
markerInterfaces
;
MethodType
[]
bridges
;
int
argIndex
=
4
;
if
((
flags
&
FLAG_MARKERS
)
!=
0
)
{
int
markerCount
=
(
Integer
)
args
[
argIndex
++];
...
...
@@ -277,30 +248,9 @@ public class LambdaMetafactory {
}
else
markerInterfaces
=
EMPTY_CLASS_ARRAY
;
if
((
flags
&
FLAG_BRIDGES
)
!=
0
)
{
int
bridgeCount
=
(
Integer
)
args
[
argIndex
++];
bridges
=
new
MethodType
[
bridgeCount
];
System
.
arraycopy
(
args
,
argIndex
,
bridges
,
0
,
bridgeCount
);
argIndex
+=
bridgeCount
;
}
else
bridges
=
EMPTY_MT_ARRAY
;
boolean
foundSerializableSupertype
=
Serializable
.
class
.
isAssignableFrom
(
invokedType
.
returnType
());
for
(
Class
<?>
c
:
markerInterfaces
)
foundSerializableSupertype
|=
Serializable
.
class
.
isAssignableFrom
(
c
);
boolean
isSerializable
=
((
flags
&
LambdaMetafactory
.
FLAG_SERIALIZABLE
)
!=
0
)
||
foundSerializableSupertype
;
if
(
isSerializable
&&
!
foundSerializableSupertype
)
{
markerInterfaces
=
Arrays
.
copyOf
(
markerInterfaces
,
markerInterfaces
.
length
+
1
);
markerInterfaces
[
markerInterfaces
.
length
-
1
]
=
Serializable
.
class
;
}
AbstractValidatingLambdaMetafactory
mf
=
new
InnerClassLambdaMetafactory
(
caller
,
invokedType
,
samMethod
,
implMethod
,
instantiatedMethodType
,
isSerializable
,
markerInterfaces
,
bridges
);
AbstractValidatingLambdaMetafactory
mf
;
mf
=
new
InnerClassLambdaMetafactory
(
caller
,
invokedType
,
samMethod
,
implMethod
,
instantiatedMethodType
,
flags
,
markerInterfaces
);
mf
.
validateMetafactoryArgs
();
return
mf
.
buildCallSite
();
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录