下面列出了org.objectweb.asm.Opcodes# PUTSTATIC 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
switch (opcode) {
case Opcodes.GETSTATIC:
pushDescriptor(desc);
break;
case Opcodes.PUTSTATIC:
popDescriptor(desc);
break;
case Opcodes.GETFIELD:
pop();
pushDescriptor(desc);
break;
case Opcodes.PUTFIELD:
popDescriptor(desc);
pop();
break;
default:
throw new RuntimeException(
"Unhandled opcode " + opcode + ", owner=" + owner + ", name=" + name + ", desc" + desc);
}
super.visitFieldInsn(opcode, owner, name, desc);
}
@Override
public MethodNode generate() {
if (this.mutable) {
this.targetField.access &= ~Opcodes.ACC_FINAL;
}
int stackSpace = this.targetIsStatic ? 0 : 1; // Stack space for "this"
int maxLocals = stackSpace + this.targetType.getSize();
int maxStack = stackSpace + this.targetType.getSize();
MethodNode method = this.createMethod(maxLocals, maxStack);
if (!this.targetIsStatic) {
method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
}
method.instructions.add(new VarInsnNode(this.targetType.getOpcode(Opcodes.ILOAD), stackSpace));
int opcode = this.targetIsStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD;
method.instructions.add(new FieldInsnNode(opcode, this.info.getClassNode().name, this.targetField.name, this.targetField.desc));
method.instructions.add(new InsnNode(Opcodes.RETURN));
return method;
}
@Override
public void visitFieldInsn(
final int opcode, final String owner, final String name, final String descriptor) {
switch (opcode) {
case Opcodes.GETSTATIC:
getstatic(owner, name, descriptor);
break;
case Opcodes.PUTSTATIC:
putstatic(owner, name, descriptor);
break;
case Opcodes.GETFIELD:
getfield(owner, name, descriptor);
break;
case Opcodes.PUTFIELD:
putfield(owner, name, descriptor);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
public void visitFieldInsn(
final int opcode, final String owner, final String name, final String descriptor) {
switch (opcode) {
case Opcodes.GETSTATIC:
getstatic(owner, name, descriptor);
break;
case Opcodes.PUTSTATIC:
putstatic(owner, name, descriptor);
break;
case Opcodes.GETFIELD:
getfield(owner, name, descriptor);
break;
case Opcodes.PUTFIELD:
putfield(owner, name, descriptor);
break;
default:
throw new IllegalArgumentException();
}
}
/**
* {@inheritDoc}
*
* @see org.objectweb.asm.MethodVisitor#visitFieldInsn(int, java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public void visitFieldInsn ( int opcode, String owner, String name, String desc ) {
JVMStackState s = this.stack;
if ( opcode == Opcodes.PUTSTATIC ) {
Object v = s.pop();
if ( ! ( v instanceof BaseType ) || ( (BaseType) v ).isTainted() ) {
// generated static cached, let's assume they are safe
if ( name.indexOf('$') < 0 && this.ref.getMethod().indexOf('$') < 0 ) {
this.parent.getAnalyzer().putstatic(this.ref);
}
}
}
else {
JVMImpl.handleFieldInsn(opcode, owner, name, desc, s);
}
if ( ( opcode == Opcodes.GETSTATIC || opcode == Opcodes.GETFIELD ) && name.indexOf('$') < 0 ) {
this.parent.getAnalyzer().instantiable(this.ref, Type.getType(desc));
}
super.visitFieldInsn(opcode, owner, name, desc);
}
private boolean isSmokeMethod(MethodNode method)
{
boolean containsArray = false;
int putstatic = 0;
int getstatic = 0;
for(AbstractInsnNode ain : method.instructions.toArray())
if(ain.getOpcode() == Opcodes.ANEWARRAY)
containsArray = true;
else if(ain.getOpcode() == Opcodes.PUTSTATIC || ain.getOpcode() == Opcodes.GETSTATIC)
if(((FieldInsnNode)ain).desc.equals("[Ljava/lang/String;"))
{
if(ain.getOpcode() == Opcodes.PUTSTATIC)
putstatic++;
else
getstatic++;
}
return containsArray && putstatic == 2 && getstatic == 2;
}
@Override
public void visitFieldInsn(int opcode,
String owner,
String name,
String desc) {
if (opcode == Opcodes.PUTFIELD && parameterLoadState == ParameterLoadState.LOADED_THIS_AND_PARAMETER
&& owner.equals(slashedClassName) && name.startsWith("this$")) {
// the field that has name starts with "this$" is generated for non-static inner class
// https://sourceforge.net/p/findbugs/bugs/1015/
mBuilder.setVariableIsSynthetic(parameterForLoadState);
}
fieldInstructionCount++;
if (isAccessMethod && this.accessOwner == null) {
this.accessOwner = owner;
this.accessName = name;
this.accessDesc = desc;
this.accessIsStatic = opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC;
this.accessForField = true;
}
visitSomeInsn();
}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
super.visitFieldInsn(opcode, owner, name, desc);
if (!instrumentationActions.trackFieldAssignments) {
return;
}
if (Opcodes.PUTFIELD != opcode && Opcodes.PUTSTATIC != opcode) {
// Only track field state and name at stores (assignments).
return;
}
for (AccessedField accessedField : accessedFields) {
if (accessedField.name.equals(name)) {
instrumentToTrackFieldState(accessedField, lineNumber);
break;
}
}
}
public void visitFieldInsn(final int opcode, String owner,
final String name, final String desc) {
owner = namer.nameClass(owner);
switch (opcode) {
case Opcodes.PUTSTATIC :
recorder.add(new PutFieldRunnable(repository, owner, name, desc, true));
break;
case Opcodes.PUTFIELD :
recorder.add(new PutFieldRunnable(repository, owner, name, desc, false));
break;
case Opcodes.GETSTATIC :
recorder.add(new GetFieldRunnable(repository, owner, name, desc, true));
break;
case Opcodes.GETFIELD :
recorder.add(new GetFieldRunnable(repository, owner, name, desc, false));
break;
}
}
@Override
public void visitFieldInsn(
final int opcode, final String owner, final String name, final String descriptor) {
switch (opcode) {
case Opcodes.GETSTATIC:
getstatic(owner, name, descriptor);
break;
case Opcodes.PUTSTATIC:
putstatic(owner, name, descriptor);
break;
case Opcodes.GETFIELD:
getfield(owner, name, descriptor);
break;
case Opcodes.PUTFIELD:
putfield(owner, name, descriptor);
break;
default:
throw new IllegalArgumentException();
}
}
@Override
protected void process(MethodContext context, FieldInsnNode node) {
boolean isStatic = node.getOpcode() == Opcodes.GETSTATIC || node.getOpcode() == Opcodes.PUTSTATIC;
CachedFieldInfo info = new CachedFieldInfo(node.owner, node.name, node.desc, isStatic);
instructionName += "_" + Type.getType(node.desc).getSort();
if (isStatic) {
props.put("class_ptr", context.getCachedClasses().getPointer(node.owner));
}
int classId = context.getCachedClasses().getId(node.owner);
context.output.append(String.format("if (!cclasses[%d] || env->IsSameObject(cclasses[%d], NULL)) { cclasses_mtx[%d].lock(); if (!cclasses[%d] || env->IsSameObject(cclasses[%d], NULL)) { if (jclass clazz = %s) { cclasses[%d] = (jclass) env->NewWeakGlobalRef(clazz); env->DeleteLocalRef(clazz); } } cclasses_mtx[%d].unlock(); %s } ",
classId,
classId,
classId,
classId,
classId,
MethodProcessor.getClassGetter(context, node.owner),
classId,
classId,
trimmedTryCatchBlock));
int fieldId = context.getCachedFields().getId(info);
props.put("fieldid", context.getCachedFields().getPointer(info));
context.output.append(String.format("if (!cfields[%d]) { cfields[%d] = env->Get%sFieldID(%s, %s, %s); %s } ",
fieldId,
fieldId,
isStatic ? "Static" : "",
context.getCachedClasses().getPointer(node.owner),
context.getStringPool().get(node.name),
context.getStringPool().get(node.desc),
trimmedTryCatchBlock));
}
public void visitFieldInsn(final int opcode, final String owner, final String name, final String descriptor) {
if (opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC) {
if(!owner.equals(me.myName)) {
getNode(owner).nodesDependingOnMyStaticFields.add(this.instx);
}else if(!localfields.contains(name + descriptor)){
//if owner is myname but field is not defined in class, find where it is defined
String origin = findLocationOfField(name, descriptor, superName, interfaces);
if(null != origin) {//include source of field and intermediate classes for inclusion.. TODO: remove, not used
Pair<ClassNode, Boolean> intermia = new Pair<ClassNode, Boolean>(this.instx.getA(), true);
getNode(origin).nodesDependingOnMyStaticFields.add(intermia);
}
}
}
}
RedirectedFieldData(Target target, FieldInsnNode node) {
super(target);
this.node = node;
this.opcode = node.getOpcode();
this.owner = Type.getObjectType(node.owner);
this.type = Type.getType(node.desc);
this.dimensions = (this.type.getSort() == Type.ARRAY) ? this.type.getDimensions() : 0;
this.isStatic = this.opcode == Opcodes.GETSTATIC || this.opcode == Opcodes.PUTSTATIC;
this.isGetter = this.opcode == Opcodes.GETSTATIC || this.opcode == Opcodes.GETFIELD;
this.isSetter = this.opcode == Opcodes.PUTSTATIC || this.opcode == Opcodes.PUTFIELD;
this.description = this.isGetter ? "field getter" : this.isSetter ? "field setter" : "handler";
}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
if (interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit == null
&& opcode == Opcodes.PUTSTATIC
&& owner.equals(internalName)) {
// It is possible that an interface initializer can sets fields of other classes.
// (b/64290760), so we test whether the owner is the same as the internalName.
interfaceFieldToAccessInCompanionMethodToTriggerInterfaceClinit =
FieldInfo.create(owner, name, desc);
}
super.visitFieldInsn(opcode, owner, name, desc);
}
public void addField(ByteCodeClass cls, int opcode, String owner, String name, String desc) {
if (cls.getOriginalClassName().equals(owner) && (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC)) {
cls.addWritableField(name);
}
addInstruction(new Field(opcode, owner, name, desc));
}
static boolean isPutStatic(final int mod) {
return (mod & Opcodes.PUTSTATIC) != 0;
}
public void visitFieldInsn(int opcode, String owner, String fieldName,
String desc) {
if (firstInstruction)
addInc();
if (logPointerChange && opcode == Opcodes.PUTFIELD
&& desc.charAt(0) == 'L') {
if (constructor && !doneSuperConstructor && name.equals(owner)
&& finalFields.contains(fieldName))
delayedFieldPointer.put(fieldName, desc);
else {
// instrument reference changes from
// putfield ...,obj,v' => ...
// to
// dup2 ...,obj,v' => ...,obj,v',obj,v'
// swap ...,obj,v',obj,v' => ...,obj,v',v',obj
// dup ...,obj,v',v',obj => ...,obj,v',v',obj,obj
// getfield ...,obj,v',v',obj,obj => ...,obj,v',v',obj,v
// invokespecial
// pointerchangelog(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
// ...,obj,v',v',obj,v => ...,obj,v'
// putfield ...,obj,v' =>
super.visitInsn(Opcodes.DUP2);
super.visitInsn(Opcodes.SWAP);
super.visitInsn(Opcodes.DUP);
super.visitFieldInsn(Opcodes.GETFIELD, owner, fieldName,
desc);
super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
LOG_INTERNAL_POINTER_CHANGE,
POINTER_CHANGE_SIGNATURE);
}
} else if (logPointerChange && opcode == Opcodes.PUTSTATIC
&& desc.charAt(0) == 'L') {
// if (finalFields.contains(fieldName)) {
// // assume field is initially null
// super.visitInsn(Opcodes.DUP);
// } else {
// instrument reference changes from
// putstatic ...,v' => ...
// to
// dup ...,v' => ...,v',v'
// ldc owner.class ...,v',v' => ...,v',v',k
// getstatic ...,v',v',k => ...,v',v',k,v
// invokespecial
// staticpointerchangelog(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Object;)V
// ...,v',v',k,v => ...,v'
super.visitInsn(Opcodes.DUP);
super.visitLdcInsn(Type.getObjectType(owner));
super.visitFieldInsn(Opcodes.GETSTATIC, owner, fieldName, desc);
super.visitMethodInsn(Opcodes.INVOKESTATIC, name,
LOG_INTERNAL_STATIC_POINTER_CHANGE,
STATIC_POINTER_CHANGE_SIGNATURE);
// }
}
super.visitFieldInsn(opcode, owner, fieldName, desc);
}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
if (DEBUG) {
System.out.println(
"Visit field access : " + owner + ":" + name + ":" + desc + ":" + isStatic);
}
AccessRight accessRight;
if (!owner.equals(visitedClassName)) {
if (DEBUG) {
System.out.println(owner + ":" + name + " field access");
}
// we are accessing another object field, and at this point the visitor is not smart
// enough to know if has seen this class before or not so we must assume the field
// is *not* accessible from the $override class which lives in a different
// hierarchy and package.
// However, since we made all package-private and protected fields public, and it
// cannot be private since the visitedClassName is not the "owner", we can safely
// assume it's public.
accessRight = AccessRight.PUBLIC;
} else {
// check the field access bits.
FieldNode fieldNode = getFieldByName(name);
if (fieldNode == null) {
// If this is an inherited field, we might not have had access to the parent
// bytecode. In such a case, treat it as private.
accessRight = AccessRight.PACKAGE_PRIVATE;
} else {
accessRight = AccessRight.fromNodeAccess(fieldNode.access);
}
}
boolean handled = false;
switch (opcode) {
case Opcodes.PUTSTATIC:
case Opcodes.GETSTATIC:
handled = visitStaticFieldAccess(opcode, owner, name, desc, accessRight);
break;
case Opcodes.PUTFIELD:
case Opcodes.GETFIELD:
handled = visitFieldAccess(opcode, owner, name, desc, accessRight);
break;
default:
System.out.println("Unhandled field opcode " + opcode);
}
if (!handled) {
super.visitFieldInsn(opcode, owner, name, desc);
}
}
/**
* Static field access visit.
* So far we do not support class initializer "clinit" that would reset the static field
* value in the class newer versions. Think about the case, where a static initializer
* resets a static field value, we don't know if the current field value was set through
* the initial class initializer or some code path, should we change the field value to the
* new one ?
* <p>
* For private static fields, the access instruction is rewritten to calls to reflection
* to access the fields value:
* <p/>
* Pseudo code for Get:
* <code>
* value = $type.fieldName;
* </code>
* becomes:
* <code>
* value = (unbox)$package/AndroidInstantRuntime.getStaticPrivateField(
* $type.class, $fieldName);
* </code>
* <p/>
* Pseudo code for Set:
* <code>
* $type.fieldName = value;
* </code>
* becomes:
* <code>
* $package/AndroidInstantRuntime.setStaticPrivateField(value, $type.class $fieldName);
* </code>
*
* @param opcode the field access opcode, can only be {@link Opcodes#PUTSTATIC} or
* {@link Opcodes#GETSTATIC}
* @param name the field name
* @param desc the field type
* @param accessRight the {@link AccessRight} for the field.
* @return true if the field access was handled or false
*/
private boolean visitStaticFieldAccess(
int opcode, String owner, String name, String desc, AccessRight accessRight) {
if (accessRight != AccessRight.PUBLIC) {
switch (opcode) {
case Opcodes.GETSTATIC:
if (DEBUG) {
System.out.println("Get static field " + name);
}
// nothing of interest is on the stack.
visitLdcInsn(Type.getType("L" + owner + ";"));
push(name);
// Stack : <target_class>
// <field_name>
invokeStatic(RUNTIME_TYPE,
Method.getMethod("Object getStaticPrivateField(Class, String)"));
// Stack : <field_value>
ByteCodeUtils.unbox(this, Type.getType(desc));
return true;
case Opcodes.PUTSTATIC:
if (DEBUG) {
System.out.println("Set static field " + name);
}
// the new field value is on top of the stack.
// box it into an Object.
box(Type.getType(desc));
visitLdcInsn(Type.getType("L" + owner + ";"));
push(name);
// Stack : <boxed_field_value>
// <target_class>
// <field_name>
invokeStatic(RUNTIME_TYPE,
Method.getMethod(
"void setStaticPrivateField(Object, Class, String)"));
return true;
default:
throw new RuntimeException(
"VisitStaticFieldAccess called with wrong opcode " + opcode);
}
}
return false;
}
@Override
public void visitFieldInsn(int opcode, String owner, String internalName, String descriptor) {
TypePool.Resolution resolution = typePool.describe(owner.replace('/', '.'));
if (resolution.isResolved()) {
FieldList<FieldDescription.InDefinedShape> candidates = resolution.resolve().getDeclaredFields().filter(strict
? ElementMatchers.<FieldDescription>named(internalName).and(hasDescriptor(descriptor))
: ElementMatchers.<FieldDescription>failSafe(named(internalName).and(hasDescriptor(descriptor))));
if (!candidates.isEmpty()) {
Replacement.Binding binding = replacement.bind(instrumentedType,
instrumentedMethod,
candidates.getOnly(),
opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC);
if (binding.isBound()) {
TypeList.Generic parameters;
TypeDescription.Generic result;
switch (opcode) {
case Opcodes.PUTFIELD:
parameters = new TypeList.Generic.Explicit(candidates.getOnly().getDeclaringType(), candidates.getOnly().getType());
result = TypeDescription.Generic.VOID;
break;
case Opcodes.PUTSTATIC:
parameters = new TypeList.Generic.Explicit(candidates.getOnly().getType());
result = TypeDescription.Generic.VOID;
break;
case Opcodes.GETFIELD:
parameters = new TypeList.Generic.Explicit(candidates.getOnly().getDeclaringType());
result = candidates.getOnly().getType();
break;
case Opcodes.GETSTATIC:
parameters = new TypeList.Generic.Empty();
result = candidates.getOnly().getType();
break;
default:
throw new IllegalStateException("Unexpected opcode: " + opcode);
}
stackSizeBuffer = Math.max(stackSizeBuffer, binding.make(parameters, result, getFreeOffset())
.apply(new LocalVariableTracingMethodVisitor(mv), implementationContext)
.getMaximalSize() - result.getStackSize().getSize());
return;
}
} else if (strict) {
throw new IllegalStateException("Could not resolve " + owner.replace('/', '.')
+ "." + internalName + descriptor + " using " + typePool);
}
} else if (strict) {
throw new IllegalStateException("Could not resolve " + owner.replace('/', '.') + " using " + typePool);
}
super.visitFieldInsn(opcode, owner, internalName, descriptor);
}