Java字节码的动态生成和增强

本文介绍如何在Java中动态生成字节码,通过一个实例展示了使用JavaCompiler进行编译,并创建StringSourceJavaObject实现源代码的构建。同时讨论了字节码增强的概念,指出其在性能分析、调试和日志记录等方面的应用,并提到了ASM和cglib等知名工具。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java字节码的动态生成
     实例
        package test;

import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class CompilerTest {

        public static void main(String[] args) throws URISyntaxException {
             
              try {
                     double value = calculate( "(1+2)*8-5");
                    System. out.println("value:" +value);
             } catch (Exception e) {
                    e.printStackTrace();
             }
             
//           try {
//                  double value = invokeMethod("CalculatorMain", "calculate");
//                  System.out.println("value:"+value);
//           } catch (Exception e) {
//                  e.printStackTrace();
//           }
       }

        private static double calculate(String expr) throws Exception {
             String className = "CalculatorMain";
             String methodName = "calculate";
             
//           String source = "public class Main{" +
//                         "public static void main(String[] args){System.out.println(\"Hello World\");}" +
//                         "}";
             
             String source = "public class "+className+"{" +
                            "public static double "+methodName+"(){return " + expr+";}"+
                            "}";
             
              //获取平台的编译器
             JavaCompiler compiler = ToolProvider. getSystemJavaCompiler();
             
              //java文件管理器
             StandardJavaFileManager fileManager = compiler.getStandardFileManager(null , null, null);
             
              //java源文件对象
             StringSourceJavaObject sourceObject = new CompilerTest.StringSourceJavaObject(className, source);
             
             Iterable<StringSourceJavaObject> fileObjects = Arrays.asList(sourceObject);
             
              //Writer writer = new BufferedWriter(new FileWriter(new File("/myclass")));
             
             
             String flag = "-d";
             String outDir = System.getProperty("user.dir" ) + "/" + "bin" ;
             
             System. out.println("outDir:" +outDir );
             
              //设置编译器要执行的操作。-d 设置编译生成的.class放到哪一个目录
             Iterable<String> stringdir = Arrays. asList(flag,outDir );
             
             System. out.println(stringdir);
             
             CompilationTask task = compiler.getTask( null, fileManager, null, stringdir, null, fileObjects);
             
              boolean result = task.call();
             
              if(result){
                    System. out.println("编译成功" );
                    
                    
                     return invokeMethod(className, methodName);
             } else{
                     throw new RuntimeException("错误的表达式");
             }
             
       }

        private static double invokeMethod(String className, String methodName)
                     throws Exception {
             ClassLoader classLoader = CompilerTest. class.getClassLoader();
              try {
                    Class<?> clazz = classLoader.loadClass(className);
                    Method method = clazz.getMethod(methodName, new Class<?>[]{});
                    Object value = method.invoke( null, new Object[]{});
                     return (Double)value;
             } catch (Exception e) {
                     throw e;
             }
       }
       
        static class StringSourceJavaObject extends SimpleJavaFileObject{

              private String content ;
              public StringSourceJavaObject(String name,String content) throws URISyntaxException{
                     super(URI.create( "String:///"+name.replace("." , "/")+Kind.SOURCE .extension ),Kind.SOURCE);//Kind.SOURCE源文件类型
                     this.content = content;
             }
             
              public CharSequence getCharContent(boolean ignoreEncodingErrors){
                     return content ;
             }
       }
}


Java字节代码的增强
     
     Java字节代码的增强的时机是在java源代码编译之后,在JVM执行之前
     非常有助于进行性能分析、调试跟踪、日志记录,也可以动态的添加一些因语法而添加的东西,可以有效的帮助开发人员从中解脱出来

     比较有名的工具有     ASM、cglib

     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值