通过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. appium-andriod自动化实现注意项

    注意项: 1.appium需要全局安装,否则run test case 报错“appium not installed” 2.启动appium命令 node /Applications/Appium. ...

  2. P5111 zhtobu3232的线段树

    P5111 zhtobu3232的线段树 维护左子树右子树的贡献和跨区间贡献 #include<bits/stdc++.h> using namespace std; typedef lo ...

  3. leetcode 66. Plus One(高精度加法)

    Given a non-negative number represented as an array of digits, plus one to the number. The digits ar ...

  4. 洛谷P1584 魔杖

    题目描述 Smart在春游时意外地得到了一种好东西——一种非常珍贵的树枝.这些树枝可以用来做优质的魔杖! 选择怎样的切割方式来制作魔杖非常重要,关键问题是——一把魔杖既不能太长.又不能太短,且制作出来 ...

  5. Xshell 主机和远程机之间的文件传输

    (1)宿主机传输文件到远程机 方法1:直接拖动文件至xshell远程机命令行界面 方法2:远程机命令行输入rz打开文件选择框 (2)远程机传输文件到宿主机 远程机命令行界面上输入sz xxx.txt( ...

  6. uC/OS-II源码分析(四)

    内核结构 1,  临界区,OS_ENTER_CRITICAL和OS_EXIT_CRITICAL 为了处理临界区代码,必须关中断,等处理完毕后,再开中断.关中断可以避免其他任务或中断进入临界区代码.uC ...

  7. Spring boot 学习 四:spring boot 配置文件 application.yml

    一 关于端口: spring boot的默认端口是8080, 如果想更改的话,在配置文件中做如下配置.ServerProperties.class会去读取这个值. server: port: 另外一种 ...

  8. 用位运算实现四则运算之加减乘除(用位运算求一个数的1/3) via Hackbuteer1

    转自:http://blog.csdn.net/hackbuteer1/article/details/7390093 ^: 按位异或:&:按位与: | :按位或 计算机系统中,数值一律用补码 ...

  9. qt 安装编译

    项目编译的时候提示 cannot find -lGL sudo apt-get install libgl1-mesa-dev

  10. 阿里云服务器,无法通过公网ip访问实例

    昨天得知阿里云esc又打折了,赶紧入手了一波,因为以前有部署过的经验,所以很快就部署上了项目,就在欣喜的访问时,却无访问. 我按照下面步骤一步一步的检测, 1.服务器上是否成功部署jdk和tomcat ...