通过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. 05-树8 File Transfer(25 point(s)) 【并查集】

    05-树8 File Transfer(25 point(s)) We have a network of computers and a list of bi-directional connect ...

  2. 【Leetcode-easy】Remove Duplicates from Sorted Array

    题目要求:删除排好序的含有重复元素的数组.返回去除重复后的数组长度,并更新原始数组.不能使用额外空间. 思路:要不额外的使用内存空间,那么只有遍历数组,count保持下一个不重复的数字,遍历过程中如果 ...

  3. 关于JMS和MQ

    2.1 什么是JMS? JMS是java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输. 2.2 什么是消息模型 ○ Point-to-Point(P2P) --- 点对点 ○ P ...

  4. win8+sdk8+vs2012+freeglut+glew开发opengl

    写给想要学习opengl的同学们. 刚开始学习opengl的时候,对于整个环境的搭建以及一些概念不太清晰,网上的资料又比较凌乱,因此在此总结一下,方便大家. 首先,是有一个windows系统,我用的是 ...

  5. matlab的代码注释

    1.注释一块代码: %{ 此处代码块 %} 2.注释数行代码: 先选中,然后用组合键Ctrl+R 取消注释,用组合键Ctrl+T 3.双%%的作用:代码分块运行,点击双%%之间的代码,再点Run Se ...

  6. laravel基础课程---8、laravel响应和视图(响应是什么)

    laravel基础课程---8.laravel响应和视图(响应是什么) 一.总结 一句话总结: 就是向请求返回的响应数据(一般为html(视图),当然也可以是变量值):所有的路由及控制器必须返回某个类 ...

  7. blog集合

    godiscoder的技术blog 一个不错的技术架构设计blog MySQLOPS 数据库与运维自动化技术分享 stone的技术blog 陈皓专栏 风雪涟漪的技术blog 华为首席科学家 张宴技术b ...

  8. C#多线程编程介绍——使用thread、threadpool、timer

    C#多线程编程介绍——使用thread.threadpool.timer 在system.threading 命名空间提供一些使得能进行多线程编程的类和接口,其中线程的创建有以下三种方法:thread ...

  9. win32com操作word(3):导入VBA常量

    导入VBA常量方法:http://blog.sina.com.cn/s/blog_a73687bc0101k8x8.html 我们之前说过,win32com组件为python提供处理COM组件(.dl ...

  10. iOS 自定义UINavigationController返回按钮

    主要代码如下: //自定义导航栏返回按钮 self.navigationItem.leftBarButtonItem = ({ //导航栏返回背景视图 UIView *view = [[UIView ...