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
