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、付费专栏及课程。

余额充值