下面列出了org.objectweb.asm.Handle#getDesc ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void invokeDynamicOnLambda(MethodVisitor mv, AbstractInsnNode ain) {
InvokeDynamicInsnNode indy = (InvokeDynamicInsnNode)ain;
Object[]bsmArgs = indy.bsmArgs;
// Is it a lambda conversion
if (indy.bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory")) {
Handle lambdaBody = (Handle)bsmArgs[1];
Detector detector = this.methodFlow.detector();
String desc = lambdaBody.getDesc();
//if (detector.isPausable(lambdaBody.getOwner(), lambdaBody.getName(), desc)) {
//if(!lambdaBody.getName().equals("<init>")) {
bsmArgs[0] = addFiberType((org.objectweb.asm.Type)bsmArgs[0]);
bsmArgs[1] = new Handle(lambdaBody.getTag(),
lambdaBody.getOwner(),
lambdaBody.getName(),
desc.replace(")", D_FIBER + ")"));
bsmArgs[2] = addFiberType((org.objectweb.asm.Type)bsmArgs[2]);
//}
//}
}
ain.accept(mv);
}
protected void _dynamic_call(Handle bsm, Object[] bsmArgs, String bootstrapDesc, String boundName) {
save_stack(false);
// these are the additional bound variables passed into the boostrap method (typically metafactory)
Expr[] boundArgs = new Expr[Type.getArgumentTypes(bootstrapDesc).length];
for(int i = boundArgs.length - 1; i >= 0; i--) {
boundArgs[i] = pop();
}
// copy the bsm and bsm args
Handle bsmCopy = new Handle(bsm.getTag(), bsm.getOwner(), bsm.getName(), bsm.getDesc());
Handle provider = new Handle(bsm.getTag(), bsm.getOwner(), bsm.getName(), bsm.getDesc());
Object[] bsmArgsCopy = new Object[bsmArgs.length];
System.arraycopy(bsmArgs, 0, bsmArgsCopy, 0, bsmArgsCopy.length);
DynamicInvocationExpr expr = new DynamicInvocationExpr(bsmCopy, bsmArgsCopy, bootstrapDesc, boundArgs, boundName);
if(expr.getType() == Type.VOID_TYPE) {
addStmt(new PopStmt(expr));
} else {
int index = currentStack.height();
Type type = assign_stack(index, expr);
push(load_stack(index, type));
}
// TODO: redo vm lambdas as static resolution calls/concrete calls.
}
/**
* Mutates a handle within an invoke virtual.
*/
private Handle mutateHandle(Handle handle) {
int opcode = handle.getTag();
String owner = handle.getOwner();
String name = handle.getName();
String descriptor = handle.getDesc();
if (owner.equals(expectedOwner) && opcode == Opcodes.H_INVOKEVIRTUAL) {
if (REPLACEMENTS.containsKey(name)) {
Replacement replacement = REPLACEMENTS.get(name);
if (replacement.descriptor.equals(descriptor)) {
MutationIdentifier id = context.registerMutation(factory, replacement.toString());
if (context.shouldMutate(id)) {
return new Handle(
opcode,
owner,
replacement.destinationName,
descriptor,
handle.isInterface());
}
}
}
}
return handle;
}
/**
* Rewrites a method handle owner to this $starkoverride class and optionally change the method
* lookup in case the lambda function was an instance method.
*
* @param handle the method handle to rewrite
* @return the new method handle to use.
*/
private Handle rewriteHandleOwner(Handle handle) {
if (handle.getOwner().equals(visitedClassName)) {
// if the target lambda captured "this", it is not a static method,
// therefore, we need to change the method signature.
MethodNode lambdaMethod =
getMethodByNameInClass(
handle.getName(), handle.getDesc(), classAndInterfaceNode);
if (lambdaMethod == null) {
throw new RuntimeException(
String.format(
"Internal stark error while locating lambda %s"
+ "in class %s, please file a bug",
handle.getName(), visitedClassName));
}
// if the original method was not static, it has now been transformed into a
// a static method during instrumentation, we should therefore adapt the
// lambda signature to include the receiver as the first parameter.
String desc =
(lambdaMethod.access & Opcodes.ACC_STATIC) == 0
? "(L" + visitedClassName + ";" + handle.getDesc().substring(1)
: handle.getDesc();
return new Handle(
// no matter what the original invoke was, we now always invoke a static
// method.
Opcodes.H_INVOKESTATIC,
visitedClassName + OVERRIDE_SUFFIX,
handle.getName(),
desc,
false);
}
return handle;
}
/**
* @param methodHandle The pre-transform method handle.
* @param mapMethodDescriptor True if the underlying descriptor should be mapped or false to leave it unchanged.
* @return The post-transform method handle.
*/
public Handle mapHandle(Handle methodHandle, boolean mapMethodDescriptor, boolean preserveDebuggability) {
String methodOwner = methodHandle.getOwner();
String methodName = methodHandle.getName();
String methodDescriptor = methodHandle.getDesc();
String newMethodOwner = mapType(methodOwner, preserveDebuggability);
String newMethodName = mapMethodName(methodName);
String newMethodDescriptor = mapMethodDescriptor ? mapDescriptor(methodDescriptor, preserveDebuggability) : methodDescriptor;
return new Handle(methodHandle.getTag(), newMethodOwner, newMethodName, newMethodDescriptor, methodHandle.isInterface());
}
private Handle newLambdaHandleFrom(Handle origHandle, boolean shadowMethodDescriptor) {
final String owner = origHandle.getOwner();
final String newOwner = owner;
final String newMethodName = origHandle.getName();
final String newMethodDescriptor = shadowMethodDescriptor ? replacer.replaceMethodDescriptor(origHandle.getDesc()) : origHandle.getDesc();
return new Handle(origHandle.getTag(), newOwner, newMethodName, newMethodDescriptor, origHandle.isInterface());
}
/**
* {@inheritDoc}
*
* @see org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn(java.lang.String, java.lang.String,
* org.objectweb.asm.Handle, java.lang.Object[])
*/
@Override
public void visitInvokeDynamicInsn ( String name, String desc, Handle bsm, Object... bsmArgs ) {
if ( bsm.getTag() == Opcodes.H_INVOKESTATIC
&& ( bsm.getName().equals("metafactory") || //$NON-NLS-1$
bsm.getName().equals("altMetafactory") ) //$NON-NLS-1$
&& bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory") && bsmArgs.length >= 2 ) { //$NON-NLS-1$
Handle h = (Handle) bsmArgs[ 1 ];
Type[] handleArgs = Type.getArgumentTypes(h.getDesc());
Type[] formalArgs = Type.getArgumentTypes(desc);
List<BaseType> args = this.stack.pop(formalArgs.length);
boolean tainted = checkTainted(formalArgs, args);
String className = Type.getObjectType(h.getOwner()).getClassName();
boolean isStatic = h.getTag() == Opcodes.H_INVOKESTATIC;
MethodReference r = new MethodReference(className, false, h.getName(), isStatic, h.getDesc());
this.foundRefs.add(r);
if ( tainted ) {
if ( !Arrays.equals(handleArgs, formalArgs) ) {
if ( this.log.isDebugEnabled() ) {
this.log.debug("Mismatch between formal args and handle args in " + this.ref + " " + name); //$NON-NLS-1$ //$NON-NLS-2$
this.log.debug("Handle arguments are " + Arrays.toString(handleArgs)); //$NON-NLS-1$
this.log.debug("Formal arguments are " + Arrays.toString(formalArgs)); //$NON-NLS-1$
this.log.debug("BSM arguments are " + Arrays.toString(bsmArgs)); //$NON-NLS-1$
}
this.parent.getAnalyzer().getState().getBench().unhandledLambda();
r.setArgumentTypes(setupTainting(r, Opcodes.INVOKEDYNAMIC, Collections.EMPTY_LIST, null, r, handleArgs));
}
else {
r.setArgumentTypes(setupTainting(r, Opcodes.INVOKEDYNAMIC, args, null, r, handleArgs));
}
this.parent.getAnalyzer().getState().getBench().taintedCall();
if ( this.log.isDebugEnabled() ) {
this.log.debug(String.format(
"In %s need to check lambda %s %s::%s %s (%s): %s", //$NON-NLS-1$
this.ref,
bsm.getTag(),
bsm.getOwner(),
bsm.getName(),
desc,
bsm.getDesc(),
Arrays.toString(bsmArgs)));
this.log.debug(String.format("In %s need to check lambda %s::%s (%s)", this.ref, h.getOwner(), h.getName(), h.getDesc())); //$NON-NLS-1$
this.log.debug("Arguments " + args); //$NON-NLS-1$
}
boolean unsafeCall = this.parent.getAnalyzer().checkMethodCall(r, Collections.singleton(this.ref), true, false);
if ( !unsafeCall ) {
this.log.debug("Call is safe"); //$NON-NLS-1$
}
this.foundCall = true;
}
else {
this.parent.getAnalyzer().getState().traceCalls(r, Collections.singleton(this.ref));
this.parent.getAnalyzer().getState().getBench().untaintedCall();
}
Type returnType = Type.getReturnType(desc);
if ( returnType != Type.VOID_TYPE ) {
this.stack.push(new BasicVariable(returnType, "return " + r, tainted)); //$NON-NLS-1$
}
}
else {
this.log.warn("Unsupported dynamic call in " + this.ref); //$NON-NLS-1$
this.log.warn(String.format(
"In %s need to check lambda %s %s::%s %s (%s): %s", //$NON-NLS-1$
this.ref,
bsm.getTag(),
bsm.getOwner(),
bsm.getName(),
desc,
bsm.getDesc(),
Arrays.toString(bsmArgs)));
}
super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
}