在ASMCodeGenerator.class中的getResult方法,会获得bytes数组,最终会根据这个字节数组生成class类,想要知道AS生成的字节码文件,就需要拦截下这个bytes数组

    1. /*
    2. * (non-Javadoc)
    3. *
    4. * @see com.googlecode.aviator.code.CodeGenerator#getResult()
    5. */
    6. @Override
    7. public Expression getResult(final boolean unboxObject) {
    8. end(unboxObject);
    9. //打断点调试这个方法,查看到bytes数组
    10. byte[] bytes = this.classWriter.toByteArray();
    11. try {
    12. Class<?> defineClass =
    13. ClassDefiner.defineClass(this.className, Expression.class, bytes, this.classLoader);
    14. Constructor<?> constructor =
    15. defineClass.getConstructor(AviatorEvaluatorInstance.class, List.class, SymbolTable.class);
    16. ClassExpression exp = (ClassExpression) constructor.newInstance(this.instance,
    17. new ArrayList<String>(this.varTokens.keySet()), this.symbolTable);
    18. exp.setLambdaBootstraps(this.lambdaBootstraps);
    19. exp.setFuncsArgs(this.funcsArgs);
    20. return exp;
    21. } catch (ExpressionRuntimeException e) {
    22. throw e;
    23. } catch (Throwable e) {
    24. if (e.getCause() instanceof ExpressionRuntimeException) {
    25. throw (ExpressionRuntimeException) e.getCause();
    26. }
    27. throw new CompileExpressionErrorException("define class error", e);
    28. }
    29. }

    找到调试中界面中的bytes数组,点击这个计算器模样的图标
    image.png
    在该界面编写代码将字节数组打印出来,点击Evaluate
    image.png
    代码如下:

    1. StringBuilder sb = new StringBuilder();
    2. for (int i = 0; i < bytes.length; i++) {
    3. if (i != 0) {
    4. sb.append(",");
    5. }
    6. sb.append(bytes[i]);
    7. }
    8. return sb.toString();

    复制result中的结果
    image.png
    编写代码将字节数组输出为文件,文件的路径最好在该项目的resource目录下,然后将文件的后缀修改成.class文件,在idea中就可以查看该class文件的内容

    1. /**
    2. *
    3. * @param dirPath 文件夹路径名
    4. * @param fileName 文件名
    5. * @param data 字节数组
    6. */
    7. private static void exportClazzToFile(String dirPath, String fileName, byte[] data) {
    8. try {
    9. File dir = new File(dirPath);
    10. if(!dir.isDirectory()) {
    11. dir.mkdirs();
    12. }
    13. File file = new File(dirPath + fileName);
    14. if (!file.exists()) {
    15. System.out.println(dirPath + fileName + " is not exist, creating...");
    16. file.createNewFile();
    17. }
    18. else {
    19. // String os = System.getProperty("os.name"); // 主要针对windows文件不区分大小写问题
    20. // if(os.toLowerCase().startsWith("win")){
    21. // // it's win
    22. // }
    23. try {
    24. int maxLoop = 9999;
    25. int renameSuffixId = 2;
    26. String[] cc = fileName.split("\\.");
    27. do {
    28. Long fileLen = file.length();
    29. byte[] fileContent = new byte[fileLen.intValue()];
    30. FileInputStream in = new FileInputStream(file);
    31. in.read(fileContent);
    32. in.close();
    33. if(!Arrays.equals(fileContent, data)) {
    34. fileName = cc[0] + "_" + renameSuffixId + "." + cc[1];
    35. file = new File(dirPath + fileName);
    36. if (!file.exists()) {
    37. System.out.println("new create file: " + dirPath + fileName);
    38. file.createNewFile();
    39. break;
    40. }
    41. }
    42. else {
    43. break;
    44. }
    45. renameSuffixId++;
    46. maxLoop--;
    47. } while (maxLoop > 0);
    48. }
    49. catch (Exception e) {
    50. System.err.println("exception in read class file..., path: " + dirPath + fileName);
    51. e.printStackTrace();
    52. }
    53. }
    54. FileOutputStream fos = new FileOutputStream(file);
    55. fos.write(data);
    56. fos.close();
    57. }
    58. catch (Exception e) {
    59. System.err.println("exception occur while export class.");
    60. e.printStackTrace();
    61. }
    62. }

    之后可以通过反编译工具,将字节码生成Java文件
    链接:https://blog.csdn.net/ezconn/article/details/115493551