通过Java动态生成class文件

今天说下JAVA中的动态编译,这个功能根据我现在的了解好像没有见到过用的,我Jio的吧,现在的一些在线代码编缉器可以用到了,这个具体我也不是很清楚。感兴趣的大家可以自已了解下。

说到动态编缉大家可能会想到,动态编缉肯定不是像我们平时运行程序似的在本地的平台就开始编译了。

动态编译其实是在程序的运行过程中对Java文件的编译或者是运行.class的文件。比如说我今天想装一波,我写个java的程序,又写了个另一个java的程序在小伙伴面秀,我只运行一个java程序可以编译另一个java并且运行它。

我们先来了解下,在JAVA的6.0版本java开始引入的动态编译这个功能。其实在java6.0以前java也可以使用动态编译,那个时候好像是用的RunTime来实现的,感兴趣的可以了解下

我们先来说下6.0以后是如何进行动坊编译的呢?

这个时候JAVA引入了JavaCompiler,这个类主要是在程序中调用JAVA编程语言的接口,这个类是没有构造函数的,是接收的ToolsProvider类下的静态函数 getSystemJavaCompiler(),这个函数的主要功能获得此平台提供的Java编程语言编译器。

下面我们看下代码是如何编写的:

 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if(compiler == null){
       System.out.println("没有得到初始化");
       return;
}
int restuld =  compiler.run(null,null,null,"D:/myjava/HelloWorld.java");
System.out.println(restuld == 0 ? "编译成功":"编译失败");

这里我来说下这里是什么意思,第一行代码是获得JAVA的编程语言的编译器,第二行是一个判空处理,这里行记得加上,小编在这里遇到了问题卡了10多分钟,我也不知道怎么回事系统没有获取到java语言的编译器,一直 报出空指针异常的问题,我寻找了好久最后加了个判空处理发现这里是空的,后来我也没有处理多运行了几次就好了,如果有朋友发现这里是怎么回事评论下的,第6行代码大家可以理解为是在进行编译java源码程序。这里有4个参数分别是:

  • 为java编译器提供参数
  • 得到java编译的输出信息
  • 接收编译的错误
  • 可变参数能传入一个或多个java源码

  

这里的返回值是如果编译成功返回的是0,编译失败返回非0.

大家可以看下面这张API的截图,可以了解下,

经过程序的运行,我成功的得到了一个HelloWorld.class文件,到这里大家先练习下上面的代码,下面部分是关于如何通过反射来执行编译生成的类。

通过反射来运行生成的Class类

讲到这里我们先来了解下URLClassLoader,这个是类加载器,在我们是用类加载器的时候构造参数是可以传入一个url数组,

我们需要讲类文件的url放到一个Url数组中,可以通过创建url数组包裹url的方式来创建一个url数组,例:

URL[] urls = new URL[]{new URL("file:/" + "D:/myjava/")};

这里new Url的时候不了解的小伙伴可以看下JAVA的API文档url有一个构造参数是传入的一个路径,这个路径是要带上协议的,比如我要加载文件我就要带上file协议,如果找不到协议可能会发生格式错误的异常。

这里的url参数是可以填写目录的,接下来我们要构造一个类加载器(URLClassLoader)可以通过这个类加载器加载我们上面生成的类。

URLClassLoader loader = new URLClassLoader(urls);

使用默认委托父级ClassLoader为指定的URL构造一个新的ClassLoader 。 在首次搜索父类加载器后,将按照为类和资源指定的顺序搜索URL。 任何以“/”结尾的URL都假定是指一个目录。 否则,URL被认为是指根据需要下载并打开的JAR文件。 接下来我们要开始加载生成的类文件了:

Class c = loader.loadClass("HelloWorld");

看到这里相比大家应该很熟悉了吧,这里和我上次给大家说的反射类似,这里拿到了一个class的对象,我们可以通过class的对象查找方法,

Method method = c.getMethod("main",String[].class);

我这里就和大家大概的说下因为我在反射的那篇博客和大家说了,这里就不详细的讲解了,这里填的两个参数的意思是,参数一:是我们要查找的方法名,参数二:是方法的参数类型,在main方法的参数列表里都会有一个String数组类型的参数,主要是接受在命令行工具下填写的参数的。通过这行命令我们拿到了一个方法。接下来开始通过invoke方法你可以理解成调用这个方法:

method.invoke(null,(Object)new String[]{});

这里我们在反射那讲说要填写一个对象,这里我们填写空就可以了,因为在java的main方法是静态的,所以可以直接调用,

这样就可以运行一个类啦,

不上反射的教程,传送门

JAVA之动态编译的更多相关文章

  1. 深入理解Java的动态编译

    前提 笔者很久之前就有个想法:参考现有的主流ORM框架的设计,造一个ORM轮子,在基本不改变使用体验的前提下把框架依赖的大量的反射设计去掉,这些反射API构筑的组件使用动态编译加载的实例去替代,从而可 ...

  2. Java的动态编译、动态加载、字节码操作

    想起来之前做的一个项目:那时候是把需要的源代码通过文件流输出到一个.java文件里,然后调用sun的Comipler接口动态编译成.class文件,然后再用专门写的一个class loader加载这个 ...

  3. Java程序动态编译Java源文件

    最近接触到公司一个项目,需要将生成的源码动态编译,记录下学习过程. 先贴出官网推荐写法: JavaCompiler.CompilationTask getTask(Writer out,        ...

  4. 动态生成java、动态编译、动态加载

    我曾经见过一个“规则引擎”,是在应用系统web界面直接编写java代码,然后保存后,规则即生效,我一直很是奇怪,这是如何实现的呢?实际这就好像jsp,被中间件动态的编译成java文件,有被动态的编译成 ...

  5. JAVA中动态编译的简单使用

    一.引用库 pom文件中申明如下: <dependencies> <!-- https://mvnrepository.com/artifact/junit/junit --> ...

  6. java动态编译笔记

    1 前言 Java的动态编译知识,真真在实际开发中并不是经常遇到.但是学习java动态编译有助于我们从更深一层次去了解java.对掌握jdk的动态代理模式,这样我们在学习其他一些开源框架的时候就能够知 ...

  7. [改善Java代码]慎用动态编译

    建议17: 慎用动态编译 //=========这篇博文暂时理解不透......... 动态编译一直是Java的梦想,从Java 6版本它开始支持动态编译了,可以在运行期直接编译.java文件,执行. ...

  8. (转载)JAVA动态编译--字节代码的操纵

    在一般的Java应用开发过程中,开发人员使用Java的方式比较简单.打开惯用的IDE,编写Java源代码,再利用IDE提供的功能直接运行Java 程序就可以了.这种开发模式背后的过程是:开发人员编写的 ...

  9. Java动态编译

    程序产生过程 下图展示了从源代码到可运行程序的过程,正常情况下先编译(明文源码到字节码),后执行(JVM加载字节码,获得类模板,实例化,方法使用).本文来探索下当程序已经开始执行,但在.class甚至 ...

随机推荐

  1. 深入浅出,JS原型链的工作原理

    前言:原型链,即原型链条.它是由原型.原型的原型.原型的原型的原型...这一规则组合成的,经常被应用于继承. 原型的作用在JS中,每个对象都有自己的原型.当我们访问对象的属性和方法时,JS会先访问对象 ...

  2. 打开Vs2010时,卡在加载工具箱内容 不动了

    我是直接打开Visual Studio 2010,而不是以打开解决方案的方式打开.然后就在左下角显示“正在从包‘Microsoft.VisualStudio.IDE.ToolboxControlsIn ...

  3. github添加ssh公钥

    使用git作为版本维护工具非常方便,而且一般个人用github作为远端库就够用了.而一般git连接github的方式采用ssh的方法,http的会略微慢一些.所以为了方便一般会在github设置中添加 ...

  4. cifs挂载远程文件出现 No such device or address错误

    1. 参考 https://www.raspberrypi.org/forums/viewtopic.php?t=82199 找了两天看到这个文章才解决了问题. 我是之前同事在windows上挂载成功 ...

  5. linux启动全过程

    参考: http://www.staroceans.org/e-book/linux-bootstrap-1.html 1. MBR里的内容属于grub grub-2.02\grub-core\boo ...

  6. MySQL性能优化/调优:默认配置的修改

    在这里罗列一下这些配置, 每次新装MySQL的时候, 最好根据实际需要调整一下这些配置: max_connections 最大并发连接数.当MySQL的并发连接达到这个设定值时,新的连接将会被拒绝.当 ...

  7. jquery新添加元素无法删除

    $("body").on('click',".delic",function(){ $(this).parent().remove(); })

  8. (转)[sh] <defunct>进程

    我也碰到僵尸进程了,必须通过关闭僵尸进程的父进程或者重启解决. 来自:http://jerrybear.blog.51cto.com/629421/387846 今日发现服务器上多了一些名称为[sh] ...

  9. oracle 11g 常用命令

    sqlplus system/123@ORCL; 查看oracle字符集: select * from nls_database_parameters where parameter ='NLS_CH ...

  10. CRC16算法之二:CRC16-CCITT-XMODEM算法的java实现

    CRC16算法系列文章: CRC16算法之一:CRC16-CCITT-FALSE算法的java实现 CRC16算法之二:CRC16-CCITT-XMODEM算法的java实现 CRC16算法之三:CR ...