这篇文章给大家分享的是有关怎么使用Java实现动态编译并动态加载的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

在D盘test目录下有个java文件:AlTest.java

publicclassAlTest{publicStringsayHello(){System.out.println("AlTest类sayHello()方法正在执行....");return"helloword";}}

现需要实现在工程已经运行过程中,进行java文件到class文件的编译操作,并运行AlTest类的方法

packagecom.piao.job;importjava.lang.reflect.Method;importjavax.tools.JavaCompiler;importjavax.tools.ToolProvider;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Configurable;importorg.springframework.scheduling.annotation.EnableScheduling;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Component;@Component@Configurable@EnableSchedulingpublicclassCompilerJob{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(CompilerJob.class);privatestaticbooleanisExecute=false;/***任务:jobtest*/@Scheduled(cron="*/10*****")publicvoidtest2(){try{if(isExecute){return;}isExecute=true;//只是测试,所以只执行一次complierAndRun();}catch(Exceptione){logger.error("test",e);}}publicvoidcomplierAndRun(){try{System.out.println(System.getProperty("user.dir"));//动态编译JavaCompilerjavac=ToolProvider.getSystemJavaCompiler();intstatus=javac.run(null,null,null,"-d",System.getProperty("user.dir")+"\target\classes","D:/test/AlTest.java");if(status!=0){System.out.println("没有编译成功!");}//动态执行Classclz=Class.forName("AlTest");//返回与带有给定字符串名的类或接口相关联的Class对象。Objecto=clz.newInstance();Methodmethod=clz.getDeclaredMethod("sayHello");//返回一个Method对象,该对象反映此Class对象所表示的类或接口的指定已声明方法Stringresult=(String)method.invoke(o);//静态方法第一个参数可为null,第二个参数为实际传参System.out.println(result);}catch(Exceptione){logger.error("test",e);}}}

运行结果:

E:zhoufysmallpiao-admin

AlTest类 sayHello()方法正在执行....

hello word

其中代码:

int status = javac.run(null, null, null, "-d", System.getProperty("user.dir")+"\target\classes","D:/test/AlTest.java");

把class文件生成到了当前工程目录下的classes目录(E:zhoufysmallpiao-adminargetclassess)所以classloader是可以加载到的,如果想知道是哪个类加载器:

Class clz = Class.forName("AlTest");//返回与带有给定字符串名的类 或接口相关联的 Class 对象。
Object o = clz.newInstance();
System.out.println(clz.getClassLoader().getSystemClassLoader());

打印的是: sun.misc.Launcher$AppClassLoader@4e0e2f2a 说明使用的是AppClassLoader

当然也可以生成到Bootstrap ClassLoader可加载的目录下

//生成到工程classes下//intstatus=javac.run(null,null,null,"-d",System.getProperty("user.dir")+"\target\classes","D:/test/AlTest.java");//生成到BootStrapClassLoader可加载目录下intstatus=javac.run(null,null,null,"-d","C:\ProgramFiles\Java\jdk1.8.0_65\jre\classes","D:/test/AlTest.java");

当然也可以自定义类加载器,把文件生成在指定的外部目录 :

publicvoidcomplierAndRun(){try{System.out.println(System.getProperty("user.dir"));//动态编译JavaCompilerjavac=ToolProvider.getSystemJavaCompiler();intstatus=javac.run(null,null,null,"-d","D:\","D:/test/AlTest.java");if(status!=0){System.out.println("没有编译成功!");}//动态执行//Classclz=Class.forName("AlTest");//返回与带有给定字符串名的类或接口相关联的Class对象。//自定义类加载器的加载路径MyClassLoadermyClassLoader=newMyClassLoader("D:\");//包名+类名Classclz=myClassLoader.loadClass("AlTest");Objecto=clz.newInstance();Methodmethod=clz.getDeclaredMethod("sayHello");//返回一个Method对象,该对象反映此Class对象所表示的类或接口的指定已声明方法Stringresult=(String)method.invoke(o);//静态方法第一个参数可为null,第二个参数为实际传参System.out.println(result);}catch(Exceptione){logger.error("test",e);}}

java动态执行代码的代码, java eval

publicclassScriptUtils{privatestaticfinalLoggerlogger=LoggerFactory.getLogger(ScriptUtils.class);/****<p>执行字符串计算</p>*@paramexpress*@paramparams*@return*@throwsScriptException*/@SuppressWarnings("unchecked")publicstatic<T,E>Eeval(Stringexpress,Map<String,T>params)throwsScriptException{ScriptEngineManagermanager=newScriptEngineManager();ScriptEngineengine=manager.getEngineByName("js");if(params==null){params=newHashMap<String,T>();}Iterator<Map.Entry<String,T>>iter=params.entrySet().iterator();Map.Entry<String,T>entry=null;while(iter.hasNext()){entry=iter.next();engine.put(entry.getKey(),entry.getValue());}Eresult=null;try{result=(E)engine.eval(express);}catch(ScriptExceptione){logger.warn("表达式执行异常:"+e.getMessage());}returnresult;}/***解析字符串,并将其当作表达式执行*@paramexpress*@paramparams*@return*@throwsScriptException*/publicstatic<T>BooleanevalBoolean(Stringexpress,Map<String,T>params){ScriptEngineManagermanager=newScriptEngineManager();ScriptEngineengine=manager.getEngineByName("js");if(params==null){params=newHashMap<String,T>();}Iterator<Map.Entry<String,T>>iter=params.entrySet().iterator();Map.Entry<String,T>entry=null;while(iter.hasNext()){entry=iter.next();engine.put(entry.getKey(),entry.getValue());}Booleanresult=null;try{result=(Boolean)engine.eval(express);}catch(ScriptExceptione){result=false;logger.warn("表达式执行异常:"+e.getMessage());}returnresult;}

感谢各位的阅读!关于“怎么使用Java实现动态编译并动态加载”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!