public static GetStaticGraph generate(String className) { ClassNode targetClass = DependencyAnalysis.getClassNode(className); GetStaticGraph staticUsageTree = new GetStaticGraph(); if (targetClass != null) handle(staticUsageTree, targetClass, 0); if (Properties.INSTRUMENT_PARENT) { handleSuperClasses(staticUsageTree, targetClass); } return staticUsageTree; }
private static void handle(GetStaticGraph staticUsageTree, String className, String methodName, int depth) { ClassNode cn = DependencyAnalysis.getClassNode(className); if (cn == null) return; handle(staticUsageTree, cn, methodName, depth); }
/** * Descend into a static method call * */ private static void handleMethodInsnNode(GetStaticGraph staticUsageTree, ClassNode cn, MethodNode mn, MethodInsnNode methodCall, int depth) { // Skip if method call is not static if (methodCall.getOpcode() != Opcodes.INVOKESTATIC) { return; } // Only collect relations for instrumentable classes String calleeClassName = methodCall.owner.replaceAll("/", "."); if (BytecodeInstrumentation.checkIfCanInstrument(calleeClassName)) { logger.debug("Handling method: " + methodCall.name); handleClassInitializer(staticUsageTree, cn, mn, methodCall.owner, depth); if (!staticUsageTree.hasStaticMethodCall(cn.name, mn.name + mn.desc, methodCall.owner, methodCall.name + methodCall.desc)) { // Add call from mn to methodCall to callgraph staticUsageTree.addStaticMethodCall(cn.name, mn.name + mn.desc, methodCall.owner, methodCall.name + methodCall.desc); handle(staticUsageTree, methodCall.owner, methodCall.name + methodCall.desc, depth); } } }
/** * Descend into a static field read * */ private static void handleFieldInsnNode(GetStaticGraph staticUsageTree, ClassNode cn, MethodNode mn, FieldInsnNode insn, int depth) { // Skip field instructions that are not reads to static fields if (insn.getOpcode() != Opcodes.GETSTATIC) { return; } // Only collect relations for instrumentable classes String calleeClassName = insn.owner.replaceAll("/", "."); if (BytecodeInstrumentation.checkIfCanInstrument(calleeClassName)) { logger.debug("Handling field read: " + insn.name); if (!staticUsageTree.hasStaticFieldRead(cn.name, mn.name + mn.desc, insn.owner, insn.name)) { handleClassInitializer(staticUsageTree, cn, mn, insn.owner, depth); // Add static read from mn to insn to static usage graph staticUsageTree.addStaticFieldRead(cn.name, mn.name + mn.desc, insn.owner, insn.name); handle(staticUsageTree, insn.owner, insn.name + insn.desc, depth); } } }
/** * Descend into a <clinit> */ private static void handleClassInitializer(GetStaticGraph staticUsageTree, ClassNode cn, MethodNode mn, String owner, int depth) { if (!staticUsageTree.hasStaticMethodCall(cn.name, mn.name + mn.desc, owner, CLASS_INIT_NAME)) { // Add call from mn to methodCall to callgraph staticUsageTree.addStaticMethodCall(cn.name, mn.name + mn.desc, owner, CLASS_INIT_NAME); // handle callee's <clinit> handle(staticUsageTree, owner, CLASS_INIT_NAME, depth); } }