今天说下JAVA中的动态编译,这个功能根据我如今的了解好像没有见到过用的,我Jio的吧,如今的一些在线代码编缉器能够用到了,这个具体我也不是很清楚。感兴趣的你们能够自已了解下。html
说到动态编缉你们可能会想到,动态编缉确定不是像咱们平时运行程序似的在本地的平台就开始编译了。java
动态编译实际上是在程序的运行过程当中对Java文件的编译或者是运行.class的文件。好比说我今天想装一波,我写个java的程序,又写了个另外一个java的程序在小伙伴面秀,我只运行一个java程序能够编译另外一个java而且运行它。编程
咱们先来了解下,在JAVA的6.0版本java开始引入的动态编译这个功能。其实在java6.0之前java也可使用动态编译,那个时候好像是用的RunTime来实现的,感兴趣的能够了解下数组
咱们先来讲下6.0之后是如何进行动坊编译的呢?编程语言
这个时候JAVA引入了JavaCompiler,这个类主要是在程序中调用JAVA编程语言的接口,这个类是没有构造函数的,是接收的ToolsProvider类下的静态函数 getSystemJavaCompiler(),这个函数的主要功能得到此平台提供的Java编程语言编译器。 ide
下面咱们看下代码是如何编写的:函数
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个参数分别是:工具
这里的返回值是若是编译成功返回的是0,编译失败返回非0.url
你们能够看下面这张API的截图,能够了解下,命令行
通过程序的运行,我成功的获得了一个HelloWorld.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方法是静态的,因此能够直接调用,
这样就能够运行一个类啦,
不上反射的教程,传送门