java - 动态
2021/8/22 17:06:09
本文主要是介绍java - 动态,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
动态编译
实际上,JAVA提供了API用于动态编译的功能.
动态编译的两种做法
-
通过Runtime调用JAVA,启动新的进程去操作
Runtime runtime = Runtime.getRuntime();
-
Process process = runtime.exec("javac -cp -D:/MyJava/ HelloWorld.java");
通过JavaCompiler动态的进行编译(6.0以后引入的新功能)
public static int compileFile(String sourceFile){ //模拟JAVA源文件地址 sourceFile = "E:/MyJava/HelloWorld.java"; //获取编译器对象 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); /* 执行编译操作 第一个参数inputStream :为JAVA编译器提供参数 第二个参数outputStream :得到JAVA编译器的输出信息 第三个参数OutputStream :接收编译器的错误信息 第四个参数:可变参数(String[]),能传入一个或者多个JAVA源文件的路径 返回值:0表示成功编译,非0表示编译失败 */ int result = compiler.run(null, System.out, System.out, sourceFile); if(result == 0){ System.out.println("编译成功"); }else{ System.out.println("编译失败"); } return result; }
JAVA-动态运行
还是那个概念,通过JAVA程序去运行JAVA的class文件
两种办法
1,通过RuntimeAPI启用新的线程去执行
Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec("java -cp -D:/MyJava/ HelloWorld.java");
2,通过反射,运行编译好的类
public static void run(String dir,String classFile)throws Exception{ //目标目录 dir = "E:/MyJava/"; //目标class文件 classFile = "HelloWorld"; //创建目录url类 URL[] urls = new URL[]{new URL("file:/"+dir)}; //获取url类加载器 URLClassLoader classLoader = new URLClassLoader(urls); //加载指定的class文件 Class clazz = classLoader.loadClass(classFile); //获取其main方法 Method mainMethod = clazz.getMethod("main", String[].class); /* 执行main方法,传递字空符数组参数 因为main方法是static方法,所以可以不用传递对象 # 强制转换的原因 * 可变参数是jdk5之后的东西 * 如果说不把这个String[]转换为Object的话 * String[]里面的每个参数,都会被当作一个新的String[]被main方法加载 * 而main方法的参数只有一个 */ mainMethod.invoke(null, (Object)new String[]{}); }
字节码修改
常见的字节码操作类库
1,BCEL 2,ASM 3,CGLIB 4,Javassist
介绍&性能对比
- 其实就是字节码文件的操作,跟反射差不多
- 使JAVA成为动态语言的原因之一
- 运行时操作字节码可以让我们实现如下功能
1,动态生成新的类
2,动态改变某个类的结构(操作属性)
Java动态性的常见两种实现方式
1,字节码操作 2,反射
性能对比
- 比反射开销小,性能高
- ASM > Javaasist性能 > 反射
- 从网上分析结果来看,性能上各种方式的差距不算太大。
* 在易用性方面: 1. JDK代理是最简单方便的,只需要使用Proxy和InvocationHandler两个类,不过只能代理接口。 2. 其次是CGLIB,也很方便,不过需要引入CGLIB的JAR包。 3. Javassist需要用用字符串拼接Java源代码,稍微会比较繁琐。 4. 最麻烦的是ASM,需要手工写字节码,一般人可能还写不出来。 * 在代理对象的创建速度上 1. JDK代理与ASM都很快,比最慢的CGLIB快20倍以上。 2. 考虑到易用性,在对接口进行动态代理时,使用JDK代理应该是最合适的。 3. 在不能使用JDK代理的情况下,可以考虑使用CGLIB或者Javassist。 4. CGLIB的缺点是创建代理对象的速度慢,Javassist的缺点是需要手动编写Java源码。 5. 如果非要在这个两个中选择一个,那么只有在对性能要求非常高的情况下选择Javassist,其他一般情况下,个人认为CGLIB是比较合适的。
这篇关于java - 动态的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-07-02springboot项目无法注册到nacos-icode9专业技术文章分享
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)