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
