package net.ptnkjke.jbeditor.logic.bcel; import net.ptnkjke.jbeditor.logic.bcel.bytecode.Editor; import net.ptnkjke.jbeditor.logic.Core; import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.*; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; /** * Утилитарный класс для BCEL */ public class BCELCore { /** * Получить байт-код определённого метода */ public static String getMethodsCode(String classFile, int indexMethod) { JavaClass javaClass = null; try { javaClass = new ClassParser(new ByteArrayInputStream(Core.INSTANCE.getClassMap().get(classFile)), classFile.replace("//", ".")).parse(); } catch (IOException e) { e.printStackTrace(); return ""; } ClassGen classGen = new ClassGen(javaClass); Method method = classGen.getMethodAt(indexMethod); MethodGen methodGen = new MethodGen(method, classGen.getClassName(), classGen.getConstantPool()); StringBuilder sb = new StringBuilder(); InstructionHandle handle = methodGen.getInstructionList().getStart(); if (handle != null) { do { Editor editor = new Editor(); try { editor.visit(handle); } catch (Exception e) { e.printStackTrace(); } sb.append(editor.getResult()).append("\n"); handle = handle.getNext(); } while (handle != null); } return sb.toString(); } /** * Получит файл графика GraphViz * * @return */ private static String getGraphVizFile(MethodGen methodGen, ClassGen classGen) { GraphVizCreator graphVizCreator = new GraphVizCreator(methodGen.getInstructionList(), classGen.getConstantPool()); File image = graphVizCreator.getImage(); if (image != null) { try { return image.toURI().toURL().toString(); } catch (MalformedURLException e) { e.printStackTrace(); } } return null; } public static String getGraphVizFile(String classFile, int methodIndex) { JavaClass javaClass = null; try { javaClass = new ClassParser(new ByteArrayInputStream(Core.INSTANCE.getClassMap().get(classFile)), classFile.replace("//", ".")).parse(); } catch (IOException e) { e.printStackTrace(); return ""; } ClassGen classGen = new ClassGen(javaClass); Method method = classGen.getMethodAt(methodIndex); MethodGen methodGen = new MethodGen(method, classGen.getClassName(), classGen.getConstantPool()); return getGraphVizFile(methodGen, classGen); } /** * Update class method * * @param javaClassName JavaClassName in format net.ptnkjke.net * @param methodIndex * @param code */ public static void updateClassMethod(String javaClassName, int methodIndex, String code) { JBcelByteParser jBcelByteParser = new JBcelByteParser(); byte[] classBytes = Core.INSTANCE.getClassMap().get(javaClassName); JavaClass javaClass = null; try { javaClass = new ClassParser( new ByteArrayInputStream(classBytes), javaClassName ).parse(); } catch (IOException e) { e.printStackTrace(); } ClassGen classGen = new ClassGen(javaClass); ConstantPoolGen constantPoolGen = classGen.getConstantPool(); jBcelByteParser.parse(code, constantPoolGen); InstructionList instructionList = jBcelByteParser.getInstructions(); Method old = classGen.getMethodAt(methodIndex); MethodGen mg = new MethodGen(old, classGen.getClassName(), classGen.getConstantPool()); mg.removeLineNumbers(); // IMPORTANT!! mg.removeLocalVariables(); // IMPORTANT!! mg.setInstructionList(instructionList); classGen.setMethodAt(mg.getMethod(), methodIndex); // .class after save byte[] bytes = classGen.getJavaClass().getBytes(); Core.INSTANCE.getClassMap().put(javaClassName, bytes); } }