java - 动态
时间:2021-08-22
本文章向大家介绍java - 动态,主要包括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是比较合适的。
原文地址:https://www.cnblogs.com/skystarry/p/15172780.html
- CentOS6.5菜鸟之旅:安装SUN JDK1.7和Tomcat7
- 协议森林10 魔鬼细节 (TCP滑窗管理)
- CMD魔法堂:获取进程路径和PID值的方法集
- .Net魔法堂:提取注释生成API文档
- CMD魔法堂:CMD进入指定目录
- Apache IIS Tomcat共存,配置全能服务器
- 协议森林11 涅槃 (TCP重新发送)
- CentOS6.5菜鸟之旅:关于搜索的shell命令
- 协议森林12 天下为公 (TCP堵塞控制)
- .Net魔法堂:AssemblyInfo.cs文件详解
- 本地php环境不支持curl_exec的解决办法
- JAVA魔法堂:读取.properties配置文件
- Python深入04 闭包
- PHP获取时间戳的毫秒
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- [记录点滴] 小心 Hadoop Speculative 调度策略
- [白话解析] 通过实例来梳理概念 :准确率 (Accuracy)、精准率(Precision)、召回率(Recall)和F值(F-Measure)
- [记录点滴] OpenResty中Redis操作总结
- [源码解析] 从TimeoutException看Flink的心跳机制
- [记录点滴] 一个解决Lua 随机数生成问题的办法
- [记录点滴] 记录一次用 IntelliJ IDEA遇到scope provided 的坑
- [记录点滴] 一个Python中实现flatten的方法
- [源码解析]Oozie来龙去脉之提交任务
- [记录点滴]Ionic编译过程的研究
- [记录点滴]OpenResty 支持http v2的问题
- [源码解析]Oozie来龙去脉之内部执行
- [记录点滴]编译安装luarocks、luacheck、luautf8
- [笔记整理] 一维搜索
- [记录点滴] 使用工具和命令对redis数据进行备份恢复
- [记录点滴]Spring Boot Admin源码分析笔记