当前位置:网站首页 > Java教程 > 正文

java动态教程



[toc]

什么是动态编程?动态编程解决什么问题?Java中如何使用?什么原理?如何改进?(需要我们一起探索,由于自己也是比较菜,一般深入不到这个程度)。

动态编程是相对于静态编程而言的,平时我们讨论比较多的就是静态编程语言,例如Java,与动态编程语言,例如JavaScript。那二者有什么明显的区别呢?简单的说就是在静态编程中,类型检查是在编译时完成的,而动态编程中类型检查是在运行时完成的。所谓动态编程就是绕过编译过程在运行时进行操作的技术,在Java中有如下几种方式:

反射

这个搞Java的应该比较熟悉,原理也就是通过在运行时获得类型信息然后做相应的操作。

动态编译

动态编译是从开始支持的,主要是通过一个接口来完成的。通过这种方式我们可以直接编译一个已经存在的java文件,也可以在内存中动态生成Java代码,动态编译执行。

调用JavaScript引擎

加入了对的支持。这是一个脚本框架,提供了让脚本语言来访问Java内部的方法。你可以在运行的时候找到脚本引擎,然后调用这个引擎去执行脚本。这个脚本API允许你为脚本语言提供Java支持。

动态生成字节码

这种技术通过操作Java字节码的方式在中生成新类或者对已经加载的类动态添加元素。

在静态语言中引入动态特性,主要是为了解决一些使用场景的痛点。其实完全使用静态编程也办的到,只是付出的代价比较高,没有动态编程来的优雅。例如依赖注入框架Spring使用了反射,而Dagger2 却使用了代码生成的方式(APT)。

例如 1: 在那些依赖关系需要动态确认的场景: 2: 需要在运行时动态插入代码的场景,比如动态代理的实现。 3: 通过配置文件来实现相关功能的场景

此处我们主要说一下通过动态生成字节码的方式,其他方式可以自行查找资料。

操作java字节码的工具有两个比较流行,一个是ASM,一个是Javassit 。

ASM :直接操作字节码指令,执行效率高,要是使用者掌握Java类字节码文件格式及指令,对使用者的要求比较高。

Javassit 提供了更高级的API,执行效率相对较差,但无需掌握字节码指令的知识,对使用者要求较低。

应用层面来讲一般使用建议优先选择,如果后续发现 成为了整个应用的效率瓶颈的话可以再考虑.当然如果开发的是一个基础类库,或者基础平台,还是直接使用吧,相信从事这方面工作的开发者能力应该比较高。

上一张国外博客的图,展示处理Java字节码的工具的关系。 接下来介绍如何使用来操作字节码

Javassit使用方法

Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加入了开放源代码JBoss 应用服务器项目,通过使用Javassist对字节码操作为JBoss实现动态AOP框架。javassist是jboss的一个子项目,其主要的优点,在于简单,而且快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。

Javassist中最为重要的是, , 以及 这几个类。

ClassPool:一个基于实现的对象容器,其中键是类名称,值是表示该类的对象。默认的使用与底层相同的类路径,因此在某些情况下,可能需要向添加类路径或类字节。

CtClass:表示一个类,这些对象可以从获得。

CtMethods:表示类中的方法。

CtFields :表示类中的字段。

动态生成一个类

下面的代码会生成一个实现了接口的类

 

上面的代码就会动态生成一个.class文件,我们使用反编译工具,例如Bytecode Viewer,查看生成的字节码文件,如下图所示。

动态添加构造函数及方法

有很多种方法添加构造函数,我们使用,他是一个的静态方法,其中有一个重载版本比较方便,如下所示。第一个参数是source text 类型的方法体,第二个为类对象。

 

这段代码执行后会生成如下java代码,代码片段是使用反编译工具产生的,可以看到构造函数的参数名被修改成了。

 

同样有很多种方法添加函数,我们使用这个比较简单的形式

 

这段代码执行后会生成如下java代码:

 

动态修改方法体

动态的修改一个方法的内容才是我们关注的重点,例如在编程方面,我们就会用到这种技术,动态的在一个方法中插入代码。 例如我们有下面这样一个类

 

我们要动态的在内存中在方法体的前后插入一些代码

 

使用反编译工具查看修改后的方法结果:

 

可以看到,在生成的字节码文件中确实增加了相应的代码。 函数输出结果为:

 

Javassit 还有许多功能,例如在方法中调用方法,异常捕捉,类型强制转换,注解相关操作等,而且其还提供了字节码层面的API()。

本文转载于https://blog.csdn.net/ShuSheng0007/article/details/

如果想对类进行修改,最好是在该类在被类加载器之前。不然在执行 或者 ,会出现 的异常。当然也可以使用 Javassit 提供的类加载器 ,解决被同一个类加载器加载冲突的问题。但是需要注意的是,不同类加载器加载的同一个类,不是相同的类。

关于这一点可以参考 https://blog.csdn.net/_/article/details/

  • 上一篇: java tiledmap教程
  • 下一篇: gitlabapi教程java
  • 版权声明


    相关文章:

  • java tiledmap教程2025-02-27 23:58:05
  • java 436集教程2025-02-27 23:58:05
  • java教程 21天学通java2025-02-27 23:58:05
  • java 贪吃蛇 教程2025-02-27 23:58:05
  • 模组教程java2025-02-27 23:58:05
  • gitlabapi教程java2025-02-27 23:58:05
  • java语言程序教程2025-02-27 23:58:05
  • java埋点教程2025-02-27 23:58:05
  • 441集教程java2025-02-27 23:58:05
  • 厦门java机构教程2025-02-27 23:58:05