下面列出了怎么用org.objectweb.asm.tree.ClassNode的API类实例代码及写法,或者点击链接到github查看源代码。
private void checkExtendsClass(ClassContext context, ClassNode classNode, int classMinSdk,
String signature) {
int api = mApiDatabase.getClassVersion(signature);
if (api > classMinSdk) {
String fqcn = ClassContext.getFqcn(signature);
String message = String.format(
"Class requires API level %1$d (current min is %2$d): `%3$s`",
api, classMinSdk, fqcn);
String name = signature.substring(signature.lastIndexOf('/') + 1);
name = name.substring(name.lastIndexOf('$') + 1);
SearchHints hints = SearchHints.create(BACKWARD).matchJavaSymbol();
int lineNumber = ClassContext.findLineNumber(classNode);
Location location = context.getLocationForLine(lineNumber, name, null,
hints);
context.report(UNSUPPORTED, location, message);
}
}
public static <T> Class<? extends T> createSubClass(Class<T> superClass, String nameSuffix, int constructorParams)
{
ClassNode superNode = createClassNode(superClass);
MethodNode constructor = findConstructor(superNode, constructorParams);
String className = superClass.getName().replace('.', '/') + "_" + nameSuffix.replace(":", "_");
ClassWriter cw = new ClassWriter(0);
cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, className, null, Type.getInternalName(superClass), null);
// Constructor
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, constructor.name, constructor.desc, null, null);
int[] opcodes = createLoadOpcodes(constructor);
for (int i = 0; i < opcodes.length; i++)
{
mv.visitVarInsn(opcodes[i], i);
}
mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(superClass), constructor.name, constructor.desc, false);
mv.visitInsn(RETURN);
mv.visitMaxs(constructorParams + 1, constructorParams + 1);
mv.visitEnd();
byte[] byteCode = cw.toByteArray();
return (Class<? extends T>) createClassFromBytes(className, byteCode);
}
private void extractDefineTypeFinalityAnnotationValues(ClassNode classNode, AnnotationNode annotation) {
int phaseValue = 1; // default to 1
String typeValue = null;
Boolean finalityValue = null;
if (annotation.values != null) {
for (int i = 0; i < annotation.values.size(); i += 2) {
String name = (String) annotation.values.get(i);
Object value = annotation.values.get(i + 1);
if(name.equals(PHASE)){
phaseValue = (int) value;
} else if(name.equals(TYPE)){
typeValue = ((String)value).replaceAll("\\.", "/");
} else if(name.equals(FINALITY)){
finalityValue = (boolean) value;
}
}
if(typeValue != null && finalityValue != null){
String className = typeValue;
if(className.equals("")){
className = classNode.superName;
}
targetTypes.add(new DefineTypeFinalityAnnotation(phaseValue, className, finalityValue));
}
}
}
public static byte[] transform(byte[] bytes) {
ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.EXPAND_FRAMES);
boolean changed = false;
Iterator<MethodNode> it = cnode.methods.iterator();
while (it.hasNext()) {
MethodNode mnode = it.next();
ReferenceDetector r = new ReferenceDetector();
mnode.accept(new RemappingMethodAdapter(mnode.access, mnode.desc, new MethodVisitor(Opcodes.ASM4) {
}, r));
if (r.found) {
it.remove();
changed = true;
}
}
if (changed) {
bytes = ASMHelper.createBytes(cnode, 0);
}
return bytes;
}
public void decompile(ClassNode cn, MethodNode mn, boolean deleteCache) {
if (cn == null) {
return;
}
Decompiler d = null;
switch (decompiler) {
case PROCYON:
d = new ProcyonDecompiler(jbm, dp);
break;
case FERNFLOWER:
d = new FernflowerDecompiler(jbm, dp);
break;
case CFR:
d = new CFRDecompiler(jbm, dp);
break;
case KRAKATAU:
d = new KrakatauDecompiler(jbm, dp);
break;
}
d.setNode(cn, mn);
if (deleteCache) {
d.deleteCache();
}
d.start();
}
public void start() {
if (!started) {
started = true;
ClassNode classNode = context.dictionary.get(instance.type());
if (classNode != null) {
MethodNode method = classNode.methods.stream().filter(mn -> mn.name.equals("run") && mn.desc.equals("()V")).findFirst().orElse(null);
if (method != null) {
Context threadContext = new Context(context.provider);
threadContext.dictionary = context.dictionary;
threadContext.file = context.file;
thread = new Thread(() -> MethodExecutor.execute(classNode, method, Collections.emptyList(), instance, threadContext));
ThreadStore.addThread(thread.getId(), this);
this.context = threadContext;
thread.start();
return;
}
throw new IllegalArgumentException("Could not find run() method on " + classNode.name);
}
throw new IllegalArgumentException("Could not find class " + instance.type());
} else {
throw new IllegalStateException("Thread already started");
}
}
/**
* Read all directly implemented interfaces from the passed {@link ClassNode} instance.
*
* @param classNode the class
* @param classReaderProvider a provider to read class bytes from storage
* @param interfacesList a builder to store the list of AsmInterfaceNode for each directly
* implemented interfaces, can be empty after method returns.
* @return true if implemented interfaces could all be loaded, false otherwise.
* @throws IOException when bytes cannot be read
*/
static boolean readInterfaces(
@NonNull ClassNode classNode,
@NonNull ClassNodeProvider classReaderProvider,
@NonNull ImmutableList.Builder<AsmInterfaceNode> interfacesList)
throws IOException {
for (String anInterface : (List<String>) classNode.interfaces) {
AsmInterfaceNode interfaceNode =
readInterfaceHierarchy(classReaderProvider, anInterface, classNode);
if (interfaceNode != null) {
interfacesList.add(interfaceNode);
} else {
return false;
}
}
return true;
}
@Override
public void visit(Map<String, ClassNode> classMap) {
classMap.values().forEach(classNode -> classNode.methods.forEach(methodNode ->
Arrays.stream(methodNode.instructions.toArray()).forEachOrdered(ain -> {
try {
final AbstractInsnNode current = ain.getNext();
if (current == null)
return;
if (!(current instanceof LineNumberNode))
return;
methodNode.instructions.iterator().set(new LineNumberNode(RandomUtil.nextInt(), ((LineNumberNode) current).start));
} catch (Exception ignored) {
}
})));
}
/**
* Given a map of ClassNodes and mappings, returns a map of class names to
* class bytes.
*
* @param nodes
* @param mappings
* @return
*/
public static Map<String, byte[]> process(Map<String, ClassNode> nodes, Map<String, MappedClass> mappings, boolean useMaxs) {
Map<String, byte[]> out = new HashMap<String, byte[]>();
SkidRemapper mapper = new SkidRemapper(mappings);
try {
for (ClassNode cn : nodes.values()) {
ClassWriter cw = new MappingClassWriter(mappings, useMaxs ? ClassWriter.COMPUTE_MAXS : ClassWriter.COMPUTE_FRAMES);
ClassVisitor remapper = new ClassRemapper(cw, mapper);
cn.accept(remapper);
out.put(mappings.containsKey(cn.name) ? mappings.get(cn.name).getNewName() : cn.name, cw.toByteArray());
}
} catch (Exception e) {
e.printStackTrace();
}
return out;
}
@Override
public void visit(Map<String, ClassNode> classMap) {
classMap.values().forEach(classNode -> {
if (!(AccessUtil.isSynthetic(classNode.access) && classNode.visibleAnnotations == null))
classNode.access |= ACC_SYNTHETIC;
classNode.methods.forEach(methodNode -> {
if (!AccessUtil.isSynthetic(methodNode.access))
methodNode.access |= ACC_SYNTHETIC;
if (!methodNode.name.startsWith("<") && AccessUtil.isBridge(methodNode.access))
methodNode.access |= ACC_BRIDGE;
});
classNode.fields.forEach(fieldNode -> {
if (!AccessUtil.isSynthetic(fieldNode.access))
fieldNode.access |= ACC_SYNTHETIC;
});
});
}
@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)");
}
@Test
public void addMethod() throws Exception {
final MethodNode methodNode = TestClassLoader.get("com.navercorp.test.pinpoint.jdk8.interfaces.SimpleClass", "welcome");
final ASMMethodNodeAdapter methodNodeAdapter = new ASMMethodNodeAdapter("com/navercorp/test/pinpoint/jdk8/interfaces/SimpleClass", methodNode);
final String targetInterfaceName = "com.navercorp.test.pinpoint.jdk8.interfaces.MethodInterface";
TestClassLoader classLoader = new TestClassLoader();
classLoader.addTargetClassName(targetInterfaceName);
classLoader.setTrace(false);
classLoader.setCallbackHandler(new CallbackHandler() {
@Override
public void handle(ClassNode classNode) {
logger.debug("Add method class={}", classNode.name);
ASMClassNodeAdapter classNodeAdapter = new ASMClassNodeAdapter(pluginContext, null, null, classNode);
classNodeAdapter.copyMethod(methodNodeAdapter);
}
});
logger.debug("Interface static method");
Class<?> clazz = classLoader.loadClass(targetInterfaceName);
Method method = clazz.getDeclaredMethod("welcome");
method.invoke(null);
}
private Class<?> addDelegatorMethod(final String targetClassName, final String superClassName, final String methodName) throws Exception {
final ClassNode superClassNode = ASMClassNodeLoader.get(superClassName);
List<MethodNode> methodNodes = superClassNode.methods;
final MethodNode methodNode = findMethodNode(methodName, methodNodes);
classLoader.setTargetClassName(targetClassName);
classLoader.setCallbackHandler(new ASMClassNodeLoader.CallbackHandler() {
@Override
public void handle(final ClassNode classNode) {
String[] exceptions = null;
if (methodNode.exceptions != null) {
exceptions = methodNode.exceptions.toArray(new String[0]);
}
final MethodNode newMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, exceptions);
final ASMMethodNodeAdapter methodNodeAdapter = new ASMMethodNodeAdapter(classNode.name, newMethodNode);
methodNodeAdapter.addDelegator(JavaAssistUtils.javaNameToJvmName(superClassName));
classNode.methods.add(newMethodNode);
}
});
return classLoader.loadClass(targetClassName);
}
private void extractMergeTypeAnnotationValues(ClassNode classNode, AnnotationNode annotation){
if(classNode != null){
int phaseValue = 1; // default to 1
String superTypeValue = null;
if(annotation.values != null){
for (int i = 0; i < annotation.values.size(); i += 2) {
String name = (String) annotation.values.get(i);
Object value = annotation.values.get(i + 1);
if(name.equals(PHASE)){
phaseValue = (int) value;
} else if(name.equals(SUPERTYPE)){
superTypeValue = ((String)value).replaceAll("\\.", "/");
}
}
}
if(superTypeValue == null || superTypeValue.equals("")){
superTypeValue = classNode.superName;
}
mergeTypeAnnotation = new MergeTypeAnnotation(phaseValue, superTypeValue);
}
}
/**
* Add a new method in the list of unseen methods in the instrumentedClass hierarchy.
*
* @param name the dispatching name that will be used for matching callers to the passed method.
* @param instrumentedClass class that is being visited
* @param superClass the class or interface defining the passed method.
* @param method the method to study
* @param methods the methods arlready encountered in the ClassNode hierarchy
* @return the newly added {@link MethodReference} of null if the method was not added for any
* reason.
*/
@Nullable
private static MethodReference addNewMethod(
String name,
ClassNode instrumentedClass,
ClassNode superClass,
MethodNode method,
Map<String, MethodReference> methods) {
if (isAccessCompatibleWithStark(method.access)
&& !methods.containsKey(name)
&& (method.access & Opcodes.ACC_STATIC) == 0
&& isCallableFromSubclass(method, superClass, instrumentedClass)) {
MethodReference methodReference = new MethodReference(method, superClass);
methods.put(name, methodReference);
return methodReference;
}
return null;
}
/**
* Creates a new ClassNode instances from the provided byte[]
*
* @param bytez the class file's byte[]
* @return the ClassNode instance
*/
public static ClassNode getNode(final byte[] bytez) throws Exception {
ClassReader cr = new ClassReader(bytez);
ClassNode cn = new ClassNode();
try {
cr.accept(cn, ClassReader.EXPAND_FRAMES);
} catch (Exception e) {
try {
cr.accept(cn, ClassReader.SKIP_FRAMES);
} catch (Exception e2) {
throw e2;
}
}
cr = null;
return cn;
}
private ArrayList<String> findNeededContents(ClassNode cn, MethodNode mn) {
ArrayList<String> neededContents = new ArrayList<>();
for (AbstractInsnNode ain : mn.instructions.toArray()) {
if (ain instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode) ain;
if (min.owner.equals(cn.name) && !neededContents.contains(min.name + min.desc)) {
neededContents.add(min.name + min.desc);
neededContents.addAll(findNeededContents(cn, ClassUtils.getMethod(cn, min.name, min.desc)));
}
}
if (ain instanceof FieldInsnNode) {
FieldInsnNode fin = (FieldInsnNode) ain;
if (fin.owner.equals(cn.name) && !neededContents.contains(fin.name + fin.desc)) {
neededContents.add(fin.name + fin.desc);
}
}
}
return neededContents;
}
@Override
public Map<String, ClassNode> getClasses() {
for (Class<?> c : ins.getAllLoadedClasses()) {
String name = c.getName().replace('.', '/');
if (!isRT(name) && !classes.containsKey(name)) {
if (name.contains("$$") || systemClasses.contains(name) || name.contains("[") || !ins.isModifiableClass(c)) {
continue;
}
try {
ClassNode cn = Loader.classToNode(name);
if (cn != null) {
classes.put(name, cn);
output.put(name, ASMUtils.getNodeBytes0(cn));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return classes;
}
public List<ClassNode> loadHierachy(ClassNode specificNode) {
if (specificNode.name.equals("java/lang/Object")) {
return Collections.emptyList();
}
if ((specificNode.access & Opcodes.ACC_INTERFACE) != 0) {
getClassTree(specificNode.name).parentClasses.add("java/lang/Object");
return Collections.emptyList();
}
List<ClassNode> toProcess = new ArrayList<>();
ClassTree thisTree = getClassTree(specificNode.name);
ClassNode superClass = assureLoaded(specificNode.superName);
if (superClass == null) {
throw new IllegalArgumentException("Could not load " + specificNode.name);
}
ClassTree superTree = getClassTree(superClass.name);
superTree.subClasses.add(specificNode.name);
thisTree.parentClasses.add(superClass.name);
toProcess.add(superClass);
for (String interfaceReference : specificNode.interfaces) {
ClassNode interfaceNode = assureLoaded(interfaceReference);
if (interfaceNode == null) {
throw new IllegalArgumentException("Could not load " + interfaceReference);
}
ClassTree interfaceTree = getClassTree(interfaceReference);
interfaceTree.subClasses.add(specificNode.name);
thisTree.parentClasses.add(interfaceReference);
toProcess.add(interfaceNode);
}
return toProcess;
}
@Parameters(name = "{0}")
public static List<Object[]> data() throws Exception {
List<Object[]> result = new ArrayList<>();
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
String fileName = path.toString();
if (!fileName.endsWith(".class")) {
return super.visitFile(path, attrs);
}
if (!fileName.startsWith("/org/testcontainers/") ) {
return super.visitFile(path, attrs);
}
if (fileName.startsWith("/" + SHADED_PACKAGE_PATH)) {
return super.visitFile(path, attrs);
}
try(InputStream inputStream = Files.newInputStream(path)) {
ClassReader reader = new ClassReader(inputStream);
ClassNode node = new ClassNode();
reader.accept(node, ClassReader.SKIP_CODE);
if ((node.access & Opcodes.ACC_PUBLIC) != 0) {
result.add(new Object[]{ fileName, node });
}
}
return super.visitFile(path, attrs);
}
});
return result;
}
@Override
public void transform(ClassNode classNode, String name) {
for (MethodNode methodNode : classNode.methods) {
if (TransformerMethod.playSound.matches(methodNode)) {
// Objective:
// Find: this.getNormalizedVolume(p_sound, soundpoolentry, soundcategory);
// Replace method with: SoundManagerHook.getNormalizedVolume(this, p_sound, soundpoolentry, soundcategory);
Iterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
while (iterator.hasNext()) {
AbstractInsnNode abstractNode = iterator.next();
if (abstractNode instanceof MethodInsnNode) {
MethodInsnNode methodInsnNode = (MethodInsnNode)abstractNode;
if (nameMatches(methodInsnNode.owner, TransformerClass.SoundManager.getNameRaw()) && TransformerMethod.getNormalizedVolume.matches(methodInsnNode)) {
methodNode.instructions.insertBefore(abstractNode, new MethodInsnNode(Opcodes.INVOKESTATIC, "codes/biscuit/skyblockaddons/asm/hooks/SoundManagerHook", "getNormalizedVolume",
"("+TransformerClass.SoundManager.getName()+TransformerClass.ISound.getName()+TransformerClass.SoundPoolEntry.getName()+TransformerClass.SoundCategory.getName()+")F",
false)); // Add SoundManagerHook.getNormalizedVolume(this, p_sound, soundpoolentry, soundcategory);
iterator.remove(); // Remove the old method call.
break;
}
}
}
break;
}
}
}
@Test
public void addField_transient() throws Exception {
final String baseClassName = "com.navercorp.pinpoint.profiler.instrument.mock.SerializableClass";
final Class<AsyncContext> asyncContextClass = AsyncContext.class;
final String accessorClassName = asyncContextClass.getName();
final ASMClassNodeLoader.TestClassLoader classLoader = ASMClassNodeLoader.getClassLoader();
classLoader.setTargetClassName(baseClassName);
classLoader.setCallbackHandler(new ASMClassNodeLoader.CallbackHandler() {
@Override
public void handle(ClassNode classNode) {
ASMClassNodeAdapter classNodeAdapter = new ASMClassNodeAdapter(pluginClassInputStreamProvider, null, getClass().getProtectionDomain(), classNode);
classNodeAdapter.addField("_$PINPOINT$_" + JavaAssistUtils.javaClassNameToVariableName(accessorClassName), Type.getDescriptor(asyncContextClass));
classNodeAdapter.addInterface(accessorClassName);
ASMFieldNodeAdapter fieldNode = classNodeAdapter.getField("_$PINPOINT$_" + JavaAssistUtils.javaClassNameToVariableName(accessorClassName), null);
classNodeAdapter.addGetterMethod("_$PINPOINT$_getAsyncContext", fieldNode);
classNodeAdapter.addSetterMethod("_$PINPOINT$_setAsyncContext", fieldNode);
}
});
Class<?> baseClazz = classLoader.loadClass(baseClassName);
Object instance = baseClazz.newInstance();
AsyncContext asyncContext = new MockAsyncContext();
Method setMethod = baseClazz.getDeclaredMethod("_$PINPOINT$_setAsyncContext", asyncContextClass);
setMethod.invoke(instance, asyncContext);
Method getMethod = baseClazz.getDeclaredMethod("_$PINPOINT$_getAsyncContext");
AsyncContext result = (AsyncContext) getMethod.invoke(instance);
JavaSerializableUtils.serialize(instance);
logger.debug("{}", result);
}
@Override
public void print(ClassNode e) {
this.sw.print(".class ").print(e.name).print(" {").tab();
this.emitDirective("superName", e.superName);
this.emitDirective("interfaces", e.interfaces);
this.emitDirective("version", e.version);
this.emitAccessDirective(e.access);
this.emitIfNonNull("sourceFile", e.sourceFile);
this.emitIfNonNull("sourceFile", e.sourceDebug);
this.emitIfNonNull("outerClass", e.outerClass);
this.emitIfNonNull("outerMethod", e.outerMethod);
this.emitIfNonNull("outerMethodDesc", e.outerMethodDesc);
if(isNonEmpty(e.visibleAnnotations)) {
this.emitDirective("visibleAnnotations", e.visibleAnnotations);
}
if(isNonEmpty(e.invisibleAnnotations)) {
this.emitDirective("invisibleAnnotations", e.invisibleAnnotations);
}
if(isNonEmpty(e.visibleTypeAnnotations)) {
this.emitDirective("visibleTypeAnnotations", e.visibleTypeAnnotations);
}
if(isNonEmpty(e.invisibleTypeAnnotations)) {
this.emitDirective("invisibleTypeAnnotations", e.invisibleTypeAnnotations);
}
if(isNonEmpty(e.attrs)) {
this.emitNodeAttributes(e.attrs);
}
this.emit(e.fields.iterator(), this.fieldPrinter);
this.emit(e.methods.iterator(), this.methodPrinter);
this.sw.untab().newline().print("}");
}
private static <T> T getAsmNode(
AsmNode asmNodeRequest,
Class<T> requestedNodeType,
List<JarTransformationRecord> jarTransformationRecords,
ImmutableList<Path> initialInputs,
String workingJavaPackage)
throws IOException, ClassNotFoundException {
String requestedClassName = asmNodeRequest.className();
String qualifiedClassName =
workingJavaPackage.isEmpty() || requestedClassName.contains(".")
? requestedClassName
: workingJavaPackage + "." + requestedClassName;
String classFileName = qualifiedClassName.replace('.', '/') + ".class";
int round = asmNodeRequest.round();
ImmutableList<Path> jars =
round == 0 ? initialInputs : jarTransformationRecords.get(round - 1).outputJars();
ClassNode classNode = findClassNode(classFileName, jars);
if (requestedNodeType == ClassNode.class) {
return requestedNodeType.cast(classNode);
}
String memberName = asmNodeRequest.memberName();
String memberDescriptor = asmNodeRequest.memberDescriptor();
if (requestedNodeType == FieldNode.class) {
return requestedNodeType.cast(getFieldNode(classNode, memberName, memberDescriptor));
}
if (requestedNodeType == MethodNode.class) {
return requestedNodeType.cast(getMethodNode(classNode, memberName, memberDescriptor));
}
throw new UnsupportedOperationException(
String.format("Injecting a node type (%s) is not supported", requestedNodeType));
}
@Nullable
protected static MethodNode getMethodByNameInClass(String methodName, String desc, ClassNode classNode) {
//noinspection unchecked ASM API
List<MethodNode> methods = classNode.methods;
for (MethodNode method : methods) {
if (method.name.equals(methodName) && method.desc.equals(desc)) {
return method;
}
}
return null;
}
public LVPEntry(ClassNode cn, MethodNode mn, LocalVariableNode lvn) {
this.cn = cn;
this.mn = mn;
this.lvn = lvn;
this.text = TextUtils.toHtml(TextUtils.toBold("#" + lvn.index) + " ");
if (lvn.desc != null && !lvn.desc.isEmpty()) {
this.text += InstrUtils.getDisplayType(lvn.desc, true) + " ";
}
this.text += TextUtils.addTag(TextUtils.escape(lvn.name), "font color=#995555");
}
@BeforeEach
public void setUp() throws IOException {
byte[] classData = readZipFromResource("SimpleStub.zip").get("SimpleStub.class");
ClassReader classReader = new ClassReader(classData);
classNode = new ClassNode();
classReader.accept(classNode, 0);
methodNode = classNode.methods.get(1); // stub should be here
}
@Test
public void nonNestInvocationInstructions(
@AsmNode(className = "NonNest", round = 0) ClassNode before,
@AsmNode(className = "NonNest", round = 1) ClassNode after) {
assertThat(before.version).isEqualTo(JdkVersion.V11);
assertThat(after.version).isEqualTo(JdkVersion.V1_7);
}
/**
* Returns true if the given class node represents an anonymous inner class
*
* @param classNode the class to be checked
* @return true if the class appears to be an anonymous class
*/
public static boolean isAnonymousClass(@NonNull ClassNode classNode) {
if (classNode.outerClass == null) {
return false;
}
String name = classNode.name;
int index = name.lastIndexOf('$');
if (index == -1 || index == name.length() - 1) {
return false;
}
return Character.isDigit(name.charAt(index + 1));
}
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);
}
}