下面列出了org.objectweb.asm.Opcodes# H_INVOKESPECIAL 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public Set<MethodNode> resolveTargets(InvocationResolver res) {
// this is probably like 99% of all the invokedynamics
if (bootstrapMethod.getOwner().equals("java/lang/invoke/LambdaMetafactory")
&& bootstrapMethod.getName().equals("metafactory")) {
assert (bootstrapArgs.length == 3 && bootstrapArgs[1] instanceof Handle);
Handle boundFunc = (Handle) bootstrapArgs[1];
switch (boundFunc.getTag()) {
case Opcodes.H_INVOKESTATIC:
return StaticInvocationExpr.resolveStaticCall(res, boundFunc.getOwner(), boundFunc.getName(), boundFunc.getDesc());
case Opcodes.H_INVOKESPECIAL:
assert(boundFunc.getName().equals("<init>"));
return VirtualInvocationExpr.resolveSpecialInvocation(res, boundFunc.getOwner(), boundFunc.getDesc());
case Opcodes.H_INVOKEINTERFACE:
case Opcodes.H_INVOKEVIRTUAL:
return VirtualInvocationExpr.resolveVirtualInvocation(res, boundFunc.getOwner(), boundFunc.getOwner(), boundFunc.getDesc());
default:
throw new IllegalArgumentException("Unexpected metafactory bootstrap tag?? " + boundFunc.getTag());
}
}
return new HashSet<>();
}
@Override
public boolean isField() {
switch (this.handle.getTag()) {
case Opcodes.H_INVOKEVIRTUAL:
case Opcodes.H_INVOKESTATIC:
case Opcodes.H_INVOKEINTERFACE:
case Opcodes.H_INVOKESPECIAL:
case Opcodes.H_NEWINVOKESPECIAL:
return false;
case Opcodes.H_GETFIELD:
case Opcodes.H_GETSTATIC:
case Opcodes.H_PUTFIELD:
case Opcodes.H_PUTSTATIC:
return true;
default:
throw new MixinTransformerError("Invalid tag " + this.handle.getTag() + " for method handle " + this.handle + ".");
}
}
/**
* Produces a {@link MethodHandle} using either the context or {@link #targetLoader} class
* loader, depending on {@code target}.
*/
private MethodHandle toMethodHandle(Lookup lookup, Handle asmHandle, boolean target)
throws ReflectiveOperationException {
Class<?> owner = loadFromInternal(asmHandle.getOwner());
MethodType signature =
MethodType.fromMethodDescriptorString(
asmHandle.getDesc(),
target ? targetLoader : Thread.currentThread().getContextClassLoader());
switch (asmHandle.getTag()) {
case Opcodes.H_INVOKESTATIC:
return lookup.findStatic(owner, asmHandle.getName(), signature);
case Opcodes.H_INVOKEVIRTUAL:
case Opcodes.H_INVOKEINTERFACE:
return lookup.findVirtual(owner, asmHandle.getName(), signature);
case Opcodes.H_INVOKESPECIAL: // we end up calling these using invokevirtual
return lookup.findSpecial(owner, asmHandle.getName(), signature, owner);
case Opcodes.H_NEWINVOKESPECIAL:
return lookup.findConstructor(owner, signature);
default:
throw new UnsupportedOperationException("Cannot resolve " + asmHandle);
}
}
private static int toTag(MethodName method) {
switch (method.invoke) {
case Interface:
return Opcodes.H_INVOKEINTERFACE;
case Special:
case SpecialInterface:
return Opcodes.H_INVOKESPECIAL;
case Static:
case StaticInterface:
return Opcodes.H_INVOKESTATIC;
case Virtual:
case VirtualInterface:
return Opcodes.H_INVOKEVIRTUAL;
default:
throw new AssertionError();
}
}
private void registerMethodHandleType(Handle handle) {
switch (handle.getTag()) {
case Opcodes.H_GETFIELD:
case Opcodes.H_GETSTATIC:
case Opcodes.H_PUTFIELD:
case Opcodes.H_PUTSTATIC:
visitFieldInsn(Opcodes.GETFIELD, handle.getOwner(), handle.getName(), handle.getDesc());
break;
case Opcodes.H_INVOKEVIRTUAL:
case Opcodes.H_INVOKEINTERFACE:
case Opcodes.H_INVOKESPECIAL:
case Opcodes.H_INVOKESTATIC:
case Opcodes.H_NEWINVOKESPECIAL:
visitMethodInsn(
Opcodes.H_INVOKEVIRTUAL,
handle.getOwner(),
handle.getName(),
handle.getDesc(),
false);
createAdditionalMethodsForDesugar(handle);
break;
default:
throw new IllegalStateException(
"MethodHandle tag is not supported: " + handle.getTag());
}
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (!name.equals(lambdaInfo.methodReference().getName())
|| !desc.equals(lambdaInfo.methodReference().getDesc())) {
super.visitMethodInsn(opcode, owner, name, desc, itf);
return;
}
boolean useBridgeMethod = false;
if (owner.equals(lambdaInfo.methodReference().getOwner())) {
if (lambdaInfo.methodReference().getTag() == Opcodes.H_NEWINVOKESPECIAL
&& lambdaInfo.bridgeMethod().getTag() != Opcodes.H_NEWINVOKESPECIAL) {
// We're changing a constructor call to a factory method call, so we unfortunately need
// to go find the NEW/DUP pair preceding the constructor call and remove it
removeLastAllocation();
}
useBridgeMethod = true;
} else if ((lambdaInfo.methodReference().getTag() == Opcodes.H_INVOKEVIRTUAL
|| lambdaInfo.methodReference().getTag() == Opcodes.H_INVOKESPECIAL)
&& hasAssignableRelation(owner, lambdaInfo.methodReference().getOwner())) {
// For rewriting instance methods calls, we consider the class hierarchy.
// This is for JDK 9: (b/62218600).
// TODO(cnsun): revisit this to make sure Desugar is fully compatible with this change
// in JDK: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/a3b3c7b6464d
useBridgeMethod = true;
}
if (useBridgeMethod) {
super.visitMethodInsn(
LambdaDesugaring.invokeOpcode(lambdaInfo.bridgeMethod()),
lambdaInfo.bridgeMethod().getOwner(),
lambdaInfo.bridgeMethod().getName(),
lambdaInfo.bridgeMethod().getDesc(),
lambdaInfo.bridgeMethod().isInterface());
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
static int invokeOpcode(Handle invokedMethod) {
switch (invokedMethod.getTag()) {
case Opcodes.H_INVOKESTATIC:
return Opcodes.INVOKESTATIC;
case Opcodes.H_INVOKEVIRTUAL:
return Opcodes.INVOKEVIRTUAL;
case Opcodes.H_INVOKESPECIAL:
case Opcodes.H_NEWINVOKESPECIAL: // Must be preceded by NEW
return Opcodes.INVOKESPECIAL;
case Opcodes.H_INVOKEINTERFACE:
return Opcodes.INVOKEINTERFACE;
default:
throw new UnsupportedOperationException("Don't know how to call " + invokedMethod);
}
}
/**
* Appends a string representation of the given handle to {@link #stringBuilder}.
*
* @param handle a handle.
*/
protected void appendHandle(final Handle handle) {
int tag = handle.getTag();
stringBuilder.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
stringBuilder.append("GETFIELD");
break;
case Opcodes.H_GETSTATIC:
stringBuilder.append("GETSTATIC");
break;
case Opcodes.H_PUTFIELD:
stringBuilder.append("PUTFIELD");
break;
case Opcodes.H_PUTSTATIC:
stringBuilder.append("PUTSTATIC");
break;
case Opcodes.H_INVOKEINTERFACE:
stringBuilder.append("INVOKEINTERFACE");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
stringBuilder.append("INVOKESPECIAL");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
stringBuilder.append("INVOKESTATIC");
isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
stringBuilder.append("INVOKEVIRTUAL");
isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
stringBuilder.append("NEWINVOKESPECIAL");
isMethodHandle = true;
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append('\n');
stringBuilder.append(tab3);
appendDescriptor(INTERNAL_NAME, handle.getOwner());
stringBuilder.append('.');
stringBuilder.append(handle.getName());
if (!isMethodHandle) {
stringBuilder.append('(');
}
appendDescriptor(HANDLE_DESCRIPTOR, handle.getDesc());
if (!isMethodHandle) {
stringBuilder.append(')');
}
if (handle.isInterface()) {
stringBuilder.append(" itf");
}
}
/**
* Appends the information about the given handle to {@link #buf buf}.
*
* @param h
* a handle, non null.
*/
protected void appendHandle(final Handle h) {
int tag = h.getTag();
buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
buf.append("GETFIELD");
break;
case Opcodes.H_GETSTATIC:
buf.append("GETSTATIC");
break;
case Opcodes.H_PUTFIELD:
buf.append("PUTFIELD");
break;
case Opcodes.H_PUTSTATIC:
buf.append("PUTSTATIC");
break;
case Opcodes.H_INVOKEINTERFACE:
buf.append("INVOKEINTERFACE");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
buf.append("INVOKESPECIAL");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
buf.append("INVOKESTATIC");
isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
buf.append("INVOKEVIRTUAL");
isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
buf.append("NEWINVOKESPECIAL");
isMethodHandle = true;
break;
}
buf.append('\n');
buf.append(tab3);
appendDescriptor(INTERNAL_NAME, h.getOwner());
buf.append('.');
buf.append(h.getName());
if (!isMethodHandle) {
buf.append('(');
}
appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
if (!isMethodHandle) {
buf.append(')');
}
if (h.isInterface()) {
buf.append(" itf");
}
}
/**
* Appends a string representation of the given handle to {@link #stringBuilder}.
*
* @param handle a handle.
*/
protected void appendHandle(final Handle handle) {
int tag = handle.getTag();
stringBuilder.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
stringBuilder.append("GETFIELD");
break;
case Opcodes.H_GETSTATIC:
stringBuilder.append("GETSTATIC");
break;
case Opcodes.H_PUTFIELD:
stringBuilder.append("PUTFIELD");
break;
case Opcodes.H_PUTSTATIC:
stringBuilder.append("PUTSTATIC");
break;
case Opcodes.H_INVOKEINTERFACE:
stringBuilder.append("INVOKEINTERFACE");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
stringBuilder.append("INVOKESPECIAL");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
stringBuilder.append("INVOKESTATIC");
isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
stringBuilder.append("INVOKEVIRTUAL");
isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
stringBuilder.append("NEWINVOKESPECIAL");
isMethodHandle = true;
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append('\n');
stringBuilder.append(tab3);
appendDescriptor(INTERNAL_NAME, handle.getOwner());
stringBuilder.append('.');
stringBuilder.append(handle.getName());
if (!isMethodHandle) {
stringBuilder.append('(');
}
appendDescriptor(HANDLE_DESCRIPTOR, handle.getDesc());
if (!isMethodHandle) {
stringBuilder.append(')');
}
if (handle.isInterface()) {
stringBuilder.append(" itf");
}
}
/**
* Appends a string representation of the given handle to {@link #stringBuilder}.
*
* @param handle a handle.
*/
protected void appendHandle(final Handle handle) {
int tag = handle.getTag();
stringBuilder.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
boolean isMethodHandle = false;
switch (tag) {
case Opcodes.H_GETFIELD:
stringBuilder.append("GETFIELD");
break;
case Opcodes.H_GETSTATIC:
stringBuilder.append("GETSTATIC");
break;
case Opcodes.H_PUTFIELD:
stringBuilder.append("PUTFIELD");
break;
case Opcodes.H_PUTSTATIC:
stringBuilder.append("PUTSTATIC");
break;
case Opcodes.H_INVOKEINTERFACE:
stringBuilder.append("INVOKEINTERFACE");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESPECIAL:
stringBuilder.append("INVOKESPECIAL");
isMethodHandle = true;
break;
case Opcodes.H_INVOKESTATIC:
stringBuilder.append("INVOKESTATIC");
isMethodHandle = true;
break;
case Opcodes.H_INVOKEVIRTUAL:
stringBuilder.append("INVOKEVIRTUAL");
isMethodHandle = true;
break;
case Opcodes.H_NEWINVOKESPECIAL:
stringBuilder.append("NEWINVOKESPECIAL");
isMethodHandle = true;
break;
default:
throw new IllegalArgumentException();
}
stringBuilder.append('\n');
stringBuilder.append(tab3);
appendDescriptor(INTERNAL_NAME, handle.getOwner());
stringBuilder.append('.');
stringBuilder.append(handle.getName());
if (!isMethodHandle) {
stringBuilder.append('(');
}
appendDescriptor(HANDLE_DESCRIPTOR, handle.getDesc());
if (!isMethodHandle) {
stringBuilder.append(')');
}
if (handle.isInterface()) {
stringBuilder.append(" itf");
}
}