下面列出了怎么用org.objectweb.asm.tree.FieldNode的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void parseViewOnNotTemplateField() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "template", Type.getDescriptor(String.class), null, null);
WisdomViewVisitor visitor = new WisdomViewVisitor(workbench, reporter, node);
visitor.visit("value", "index");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("template");
assertThat(element.getAttribute("filter")).contains("=index)");
}
public static PrefixedStringBuilder decompile(PrefixedStringBuilder sb,
FieldNode f) {
String s = getAccessString(f.access);
sb.append(s);
if (s.length() > 0)
sb.append(" ");
sb.append(Type.getType(f.desc).getClassName());
sb.append(" ");
sb.append(f.name);
if (f.value != null) {
sb.append(" = ");
if (f.value instanceof String) {
sb.append("\"");
sb.append(f.value);
sb.append("\"");
} else {
sb.append(f.value);
sb.append(" (");
sb.append(f.value.getClass().getCanonicalName());
sb.append(")");
}
}
sb.append(";");
return sb;
}
public static Map<String, String> renameFields(Map<String, ClassNode> classMap, Map<String, ClassInfo> classInfoMap) {
Map<String, String> newFieldsMappingsForRemapper = new HashMap<>();
NameGenerator generator = new NameGenerator();
for (Map.Entry<String, ClassNode> e : classMap.entrySet()) {
String className = e.getKey();
List<FieldNode> fieldNodes = e.getValue().fields;
for (FieldNode f : fieldNodes) {
if (!newFieldsMappingsForRemapper.containsKey(makeFullFieldName(className, f.name))) {
String newName = generator.getNextMethodOrFieldName(null);
newFieldsMappingsForRemapper.put(makeFullFieldName(className, f.name), newName);
printInfo(className, f.name, newName);
for (ClassInfo c : classInfoMap.get(className).getChildren()) {
newFieldsMappingsForRemapper.put(makeFullFieldName(c.getClassName(), f.name), newName);
printInfo(c.getClassName(), f.name, newName);
}
}
}
}
return newFieldsMappingsForRemapper;
}
@Test
public void parseModelOnNotCrudField() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "model", Type.getDescriptor(String.class), null, null);
WisdomModelVisitor visitor = new WisdomModelVisitor(workbench, reporter, node);
visitor.visit("value", "entity");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("model");
assertThat(element.getAttribute("filter")).contains("=entity)");
}
@Override
public void obfuscate() {
int stringLength = getStringLength();
System.out.println("Obfuscating fields names...");
for (ClassNode c : BytecodeViewer.getLoadedClasses()) {
for (Object o : c.fields.toArray()) {
FieldNode f = (FieldNode) o;
String newName = generateUniqueName(stringLength);
BytecodeViewer.refactorer.getHooks().addField(new FieldMappingData(c.name, new MappingData(f.name, newName), f.desc));
/*ASMUtil_OLD.renameFieldNode(c.name, f.name, f.desc, null, newName, null);
f.name = newName;*/
}
}
System.out.println("Obfuscated field names.");
}
protected static void convertXLoads(final InstructionGroup group)
{
final String owner = group.getGroupClassType().getInternalName();
InsnList insnList;
for (final InstructionGraphNode node : group.getNodes()) {
if (!node.isXLoad())
continue;
final VarInsnNode insn = (VarInsnNode) node.getInstruction();
final FieldNode field = group.getFields().get(insn.var);
final FieldInsnNode fieldNode = new FieldInsnNode(GETFIELD, owner,
field.name, field.desc);
insnList = group.getInstructions();
// insert the correct GETFIELD after the xLoad
insnList.insert(insn, fieldNode);
// change the load to ALOAD 0
insnList.set(insn, new VarInsnNode(ALOAD, 0));
}
}
private static FieldNode getFieldNode(
ClassNode classNode, String fieldName, String fieldDescriptor) {
for (FieldNode field : classNode.fields) {
if (fieldName.equals(field.name)) {
checkState(
fieldDescriptor.isEmpty() || fieldDescriptor.equals(field.desc),
"Found name-matched field but with a different descriptor. Expected requested field"
+ " descriptor, if specified, agrees with the actual field type. Field name <%s>"
+ " in class <%s>; Requested Type <%s>; Actual Type: <%s>.",
fieldName,
classNode.name,
fieldDescriptor,
field.desc);
return field;
}
}
throw new IllegalStateException(
String.format("Field <%s> not found in class <%s>", fieldName, classNode.name));
}
/**
* Returns true if the given class node represents a static inner class.
*
* @param classNode the inner class to be checked
* @return true if the class node represents an inner class that is static
*/
public static boolean isStaticInnerClass(@NonNull ClassNode classNode) {
// Note: We can't just filter out static inner classes like this:
// (classNode.access & Opcodes.ACC_STATIC) != 0
// because the static flag only appears on methods and fields in the class
// file. Instead, look for the synthetic this pointer.
@SuppressWarnings("rawtypes") // ASM API
List fieldList = classNode.fields;
for (Object f : fieldList) {
FieldNode field = (FieldNode) f;
if (field.name.startsWith("this$") && (field.access & Opcodes.ACC_SYNTHETIC) != 0) {
return false;
}
}
return true;
}
public boolean loadFields(ClassNode cn) {
this.currentClass = cn;
this.currentMethod = null;
LazyListModel<InstrEntry> lm = new LazyListModel<InstrEntry>();
editor.setText(cn.name + " Fields");
ArrayList<InstrEntry> entries = new ArrayList<>();
for (FieldNode fn : cn.fields) {
InstrEntry entry = new FieldEntry(cn, fn);
lm.addElement(entry);
entries.add(entry);
}
this.setModel(lm);
//update sidebar
if (adressList != null) {
adressList.updateAdr();
}
if (errorList != null) {
errorList.updateErrors();
}
return true;
}
@Test
public void parseRegularModel() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "model", Type.getDescriptor(Crud.class), null, null);
WisdomModelVisitor visitor = new WisdomModelVisitor(workbench, reporter, node);
visitor.visit("value", "entity");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("model");
assertThat(element.getAttribute("filter")).contains("=entity)");
}
@Override
public void obfuscate() {
int stringLength = getStringLength();
System.out.println("Obfuscating fields names...");
for (ClassNode c : BytecodeViewer.getLoadedClasses()) {
for (Object o : c.fields.toArray()) {
FieldNode f = (FieldNode) o;
String newName = generateUniqueName(stringLength);
ASMUtil_OLD.renameFieldNode(c.name, f.name, f.desc, null,
newName, null);
f.name = newName;
}
}
System.out.println("Obfuscated field names.");
}
@Override
public void process(ProcessorCallback callback, ClassNode node) {
if (!enabled.getObject()) return;
if ((node.access & Opcodes.ACC_INTERFACE) == 0) {
for (MethodNode method : node.methods) {
// if ((method.access & Opcodes.ACC_BRIDGE) == 0 && (method.access & Opcodes.ACC_STATIC) == 0 && !method.name.startsWith("<")) {
// method.access |= Opcodes.ACC_BRIDGE;
// }
// if ((method.access & Opcodes.ACC_SYNTHETIC) == 0) {
if (method.name.startsWith("<"))
continue;
if ((method.access & Opcodes.ACC_NATIVE) == 0) {
continue;
}
method.access = method.access | Opcodes.ACC_BRIDGE;
method.access = method.access | Opcodes.ACC_SYNTHETIC;
// }
}
}
for (FieldNode field : node.fields) {
// if ((field.access & Opcodes.ACC_FINAL) == 0)
field.access = field.access | Opcodes.ACC_SYNTHETIC;
}
// if ((node.access & Opcodes.ACC_FINAL) == 0) {
// node.access = node.access | Opcodes.ACC_SYNTHETIC;
// }
inst.setWorkDone();
}
public static void clearFieldAnnotations(FieldNode field) {
// clear visible annotations
if(field.visibleAnnotations != null) field.visibleAnnotations.clear();
if(field.visibleTypeAnnotations != null) field.visibleTypeAnnotations.clear();
// clear invisible annotations
if(field.invisibleAnnotations != null) field.invisibleAnnotations.clear();
if(field.invisibleTypeAnnotations != null) field.invisibleTypeAnnotations.clear();
}
@Override
public void pass(ClassNode classNode, InstrumentationState state) {
Validate.notNull(classNode);
Validate.notNull(state);
// Methods attributes should be assigned at this point.
Validate.validState(!state.methodAttributes().isEmpty());
Validate.validState(state.methodAttributes().keySet().stream().allMatch(x -> x != null));
Validate.validState(state.methodAttributes().values().stream().allMatch(x -> x != null));
// Sanity check to make sure that we're only dealing with methodnodes in the classnode -- this should never trigger unless previous
// passes mess up
Validate.validState(classNode.methods.containsAll(state.methodAttributes().keySet()));
// Instrument the methods based on the analysis we did in previous passes
MethodInstrumenter instrumenter = new MethodInstrumenter();
for (Entry<MethodNode, MethodAttributes> method : state.methodAttributes().entrySet()) {
MethodNode methodNode = method.getKey();
MethodAttributes methodAttrs = method.getValue();
// Instrument
instrumenter.instrument(classNode, methodNode, methodAttrs);
}
// Add the "Instrumented" marker field to this class so if we ever come back to it, we can skip it
FieldNode instrumentedMarkerField = new FieldNode(
INSTRUMENTED_MARKER_FIELD_ACCESS,
INSTRUMENTED_MARKER_FIELD_NAME,
INSTRUMENTED_MARKER_FIELD_TYPE.getDescriptor(),
null,
INSTRUMENTED_MARKER_FIELD_VALUE);
classNode.fields.add(instrumentedMarkerField);
}
private static void generateFields(final InstructionGroup group,
final ClassWriter cw)
{
// TODO: fix the below comment; those "two members" should be split
// CAUTION: the FieldNode has illegal access flags and an illegal
// value field since these two members are reused for other
// purposes, so we need to write out the field "manually" here
// rather than just call "field.accept(cw)"
for (final FieldNode field: group.getFields())
cw.visitField(ACC_PUBLIC + ACC_SYNTHETIC, field.name, field.desc,
null, null);
}
/**
* Finds references to the class's field in the given method.
*
* @param target
* @param targetField
* @param method
* @return
*/
public static List<Reference> getReferences(ClassNode target, FieldNode targetField, ClassNode inThisNode, MethodNode method) {
List<Reference> references = new ArrayList<Reference>();
for (AbstractInsnNode ain : method.instructions.toArray()) {
if (ain.getType() == AbstractInsnNode.FIELD_INSN) {
FieldInsnNode fin = (FieldInsnNode) ain;
if (fin.owner.contains(target.name) && fin.name.equals(targetField.name) && fin.desc.equals(targetField.desc)) {
references.add(new Reference(inThisNode, method, ain));
}
}
}
return references;
}
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
FieldVisitor fv;
if (isInterface) {
// store the fields to write them to the generated class at the end. Fields will be removed from the interface in InterfaceFieldNameMappingVisitor.
FieldNode field = new FieldNode(access, name, descriptor, signature, value);
fields.add(field);
fv = null;
} else {
fv = super.visitField(access, name, descriptor, signature, value);
}
return fv;
}
private static void initObject(Context context, String className, JavaValue object) {
ClassNode classNode = context.dictionary.get(className);
if (classNode != null) {
for (FieldNode field : classNode.fields) {
switch (field.desc) {
case "B":
context.provider.setField(classNode.name, field.name, field.desc, object, (byte) 0, context);
break;
case "S":
context.provider.setField(classNode.name, field.name, field.desc, object, (short) 0, context);
break;
case "I":
context.provider.setField(classNode.name, field.name, field.desc, object, 0, context);
break;
case "J":
context.provider.setField(classNode.name, field.name, field.desc, object, 0L, context);
break;
case "F":
context.provider.setField(classNode.name, field.name, field.desc, object, 0.0, context);
break;
case "D":
context.provider.setField(classNode.name, field.name, field.desc, object, 0.0D, context);
break;
case "C":
context.provider.setField(classNode.name, field.name, field.desc, object, (char) 0, context);
break;
case "Z":
context.provider.setField(classNode.name, field.name, field.desc, object, false, context);
break;
}
}
} else {
throw new RuntimeException("Could not initialize class " + className);
}
}
/**
* Creates the visitor.
* @param workbench the workbench
* @param reporter the reporter
* @param node the field node.
*/
public WisdomViewVisitor(ComponentWorkbench workbench, Reporter reporter, FieldNode node) {
super(Opcodes.ASM5);
this.reporter = reporter;
this.workbench = workbench;
this.node = node;
this.field = node.name;
}
public JavaField getDeclaredField(String fieldName) {
for (FieldNode fieldNode : this.classNode.fields) {
if (fieldNode.name.equals(fieldName))
return new JavaField(this, fieldNode);
}
Utils.sneakyThrow(new NoSuchFieldException(fieldName));
return null;
}
/**
* Get a list of wrapped ElementNodes for the fields of the supplied owner
* class
*
* @param owner Class to get fields, must not be <tt>null</tt>
* @return List of wrapped nodes
*/
public static List<ElementNode<FieldNode>> fieldList(ClassNode owner) {
List<ElementNode<FieldNode>> fields = new ArrayList<ElementNode<FieldNode>>();
for (FieldNode field : owner.fields) {
fields.add(new ElementNodeField(owner, field));
}
return fields;
}
/**
* Creates a FieldWrapper object.
*
* @param fieldNode the {@link FieldNode} attached to this FieldWrapper.
* @param owner the owner of this represented field.
*/
public FieldWrapper(FieldNode fieldNode, ClassWrapper owner) {
this.fieldNode = fieldNode;
this.originalName = fieldNode.name;
this.originalDescription = fieldNode.desc;
this.access = new FieldAccess(this);
this.owner = owner;
}
@Nullable
FieldNode getField(FieldInsnNode fieldInsnNode)
{
TransformerFieldPair fieldPair = this.getFieldPair(fieldInsnNode);
if (fieldPair == null)
{
return null;
}
return fieldPair.node;
}
/**
* Returns whether the given issue is suppressed in the given method.
*
* @param issue the issue to be checked, or null to just check for "all"
* @param classNode the class containing the issue
* @param method the method containing the issue
* @param instruction the instruction within the method, if any
* @return true if there is a suppress annotation covering the specific
* issue on this method
*/
public boolean isSuppressed(
@Nullable Issue issue,
@NonNull ClassNode classNode,
@NonNull MethodNode method,
@Nullable AbstractInsnNode instruction) {
if (method.invisibleAnnotations != null) {
@SuppressWarnings("unchecked")
List<AnnotationNode> annotations = method.invisibleAnnotations;
return isSuppressed(issue, annotations);
}
// Initializations of fields end up placed in generated methods (<init>
// for members and <clinit> for static fields).
if (instruction != null && method.name.charAt(0) == '<') {
AbstractInsnNode next = LintUtils.getNextInstruction(instruction);
if (next != null && next.getType() == AbstractInsnNode.FIELD_INSN) {
FieldInsnNode fieldRef = (FieldInsnNode) next;
FieldNode field = findField(classNode, fieldRef.owner, fieldRef.name);
if (field != null && isSuppressed(issue, field)) {
return true;
}
} else if (classNode.outerClass != null && classNode.outerMethod == null
&& isAnonymousClass(classNode)) {
if (isSuppressed(issue, classNode)) {
return true;
}
}
}
return false;
}
/**
* Create - no customization case
* not used for TOP or other built-in predefined types
* @return the class as a byte array
*/
byte[] createJCasCoverClass(TypeImpl type) {
this.type = type;
this.tsi = (TypeSystemImpl) type.getTypeSystem();
typeJavaDescriptor = type.getJavaDescriptor();
typeJavaClassName = type.getName().replace('.', '/');
cn = new ClassNode(ASM5); // java 8
cn.version = javaClassVersion;
cn.access = ACC_PUBLIC + ACC_SUPER;
cn.name = typeJavaClassName;
cn.superName = type.getSuperType().getName().replace('.', '/');
// cn.interfaces = typeImpl.getInterfaceNamesArray(); // TODO
// add the "type" field - this has the int type code
cn.fields.add(new FieldNode(ACC_PUBLIC + ACC_FINAL + ACC_STATIC,
"type", "I", null, null));
// add field declares, and getters and setters, and special getters/setters for array things
type.getMergedStaticFeaturesIntroducedByThisType().stream()
.forEach(this::addFeatureFieldGetSet);
addStaticInitAndConstructors();
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cn.accept(cw);
return cw.toByteArray();
}
private static boolean isEnumSwitchInitializer(ClassNode classNode) {
@SuppressWarnings("rawtypes") // ASM API
List fieldList = classNode.fields;
for (Object f : fieldList) {
FieldNode field = (FieldNode) f;
if (field.name.startsWith(ENUM_SWITCH_PREFIX)) {
return true;
}
}
return false;
}
/**
* Refresh tables.
*
* @param node
* Updated node.
*/
public void refresh(ClassNode node) {
this.node = node;
ObservableList<FieldNode> src = FXCollections.observableArrayList(this.node.fields);
ObservableList<MethodNode> src2 = FXCollections.observableArrayList(this.node.methods);
Platform.runLater(() -> {
fields.setItems(src);
methods.setItems(src2);
});
}
@Override
public void selectMember(String name, String desc) {
boolean method = desc.contains("(");
int i = 0;
TableView<?> target;
if (method) {
selectionModelProperty().get().select(tabMethods);
for (MethodNode mn : methods.getItems()) {
if (mn.name.equals(name) && mn.desc.equals(desc))
break;
i++;
}
target = methods;
} else {
selectionModelProperty().get().select(tabFields);
for (FieldNode fn : fields.getItems()) {
if (fn.name.equals(name) && fn.desc.equals(desc))
break;
i++;
}
target = fields;
}
if (i < target.getItems().size()) {
int idx = i;
Platform.runLater(() -> {
target.requestFocus();
target.getSelectionModel().select(idx);
target.getFocusModel().focus(idx);
});
}
}
FieldNode getFieldByName( String fieldName) {
FieldNode fieldNode = getFieldByNameInClass(fieldName, classNode);
Iterator<ClassNode> iterator = parentNodes.iterator();
while (fieldNode == null && iterator.hasNext()) {
ClassNode parentNode = iterator.next();
fieldNode = getFieldByNameInClass(fieldName, parentNode);
}
return fieldNode;
}
protected static FieldNode getFieldByNameInClass(
String fieldName, ClassNode classNode) {
//noinspection unchecked ASM api.
List<FieldNode> fields = classNode.fields;
for (FieldNode field : fields) {
if (field.name.equals(fieldName)) {
return field;
}
}
return null;
}