Java高阶技术(JVM\\u0026ByteCode)及其运用

大多数人谈论很多JAVA语言,这对我来说可能听起来很奇怪,但我忍不住注意到它。 JVM 是Java 生态系统的核心。

——Java之父[詹姆斯·高斯林]

我很喜欢创始人的这句话,觉得只有了解了核心技术才算是懂了。一旦你熟练掌握了某项技术,一切都在这个体系下变得更容易学习、应用和创造,让你更好地发挥个人的想象力和创造力,去做更有价值的事情。

当我们从Java学徒开始时,我们逐渐学习使用Java语言编写项目。几年后,大家大概都会和我一样拥有同样的想象力和发展空间。语言限制使我无法成功完成手头的许多任务。我觉得这和我们的学习路径有关,大多数人学习Java都是从HelloWorld开始,学习变量、函数、逻辑控制、循环、异常等。项目是为了满足成就感。很多快速教程都是为了让你快速入门而设计的,并没有提供对Java原理和技术栈的详细、系统的介绍。本文提供与Java 虚拟机(JVM) 和字节码相关的技术内容。梳理整套应用场景的目的是让大家对Java核心技术有一个新的认识。

为了帮助读者快速理解我们接下来要讨论的内容,我们将从本文的关键词开始。你还可以根据对这些技术关键词的数量和深度的理解来估计你对这些核心Java技术的理解。

JVM、ByteCode、ASM、AspectJ、CGLib、仪器、javaagent、JVMTI、Btrace、byteman

可插入注释处理API

附加API

Java编译器API

所有这些技术都围绕着JVM 和ByteCode 相关领域。我认为这些技术的核心内容是高级Java技术。主要原因是我们认为这些技术非常Hacky,这体现在几个方面。

这些技术处于Java技术栈的最底层,大多数Java程序员对这些技术的理解并不深入。

这些技术在实践中得到了广泛的应用,是现在所有主流框架的核心技术。

这些技术具有非常广泛的可能性,可以解决许多使用传统方法无法解决的问题。

由于涉及到的技术非常多,这里我们不会详细讨论每项技术。主要目的是让你有一个系统的了解。在本文的最后,我会附上我整理和挑选的相关资料。大家进一步研究、审阅。

JVM 和ByteCode 概述JVM 不运行Java,但它运行ByteCode

首先我们来介绍一下JVM的架构。 JVM 规范定义了一组子系统及其外部行为。 JVM主要由以下子系统组成:

类加载器用于读取.class字节码文件并将类加载到数据区域。

执行引擎用于执行数据区中的指令。操作系统向JVM提供实内存来访问JVM数据区中的数据。

如果您想了解更多关于JVM 原理的信息,请参阅本文末尾的参考文档。本文不会过多解释JVM 的内部结构。从这个图中可以看出,JVM执行的并不是Java文件,而是用来写入ByteCode的文件。这一点给了我们想象的空间,也留下了很多可能性。黑客攻击的可能性。您还可以更改ByteCode 的值以插入执行以前无法完成的操作的代码。通过分析ByteCode,还可以执行分析锁使用风险、分析代码逻辑结构等分析统计任务。

类文件结构概述

类文件具有非常严格的结构,Oracle 发布的JVM 标准中有详细说明。

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html

代码属性{

u2attribute_name_index; //uft8类型在常量池中的索引,值固定为“Code”

u4attribute_length; //属性值的长度,即整个属性表的长度- 6

u2 max_stack; //操作数栈的最大深度值。 jvm根据这个值运行并检查栈帧。

u2 max_locals; //局部变量表最大存储区域,单位为slot

u4 code_length; //字节码指令数

u1 code[code_length]; //具体字节码指令

u2Exception_table_length; //异常数量

{ u2 开始_pc;

u2 结束_pc;

u2 handler_pc; //如果catch_type或subclass在字节码范围[start_pc, end_pc)内,则移至handler_pc行并继续处理。

u2 catch_type; //如果catch_type=0,异常必须转发给handler_pc处理。

} Exception Table [Exception Table Length] //具体异常的内容

u2attributs_count; //属性数量

attribute_info attribute [attributes_count] //具体属性的内容

}

修改类文件的工具

要实现一些Hack功能,首先需要解决的是添加、修改、读取class文件的问题。有许多现成的字节码工具可用。这里我们介绍一下无处不在的ASM,它是使用最广泛的字节码工具之一(可以说,ASM 以其神一般的存在而著称,其设计是由其性能简单性驱动实现的)。它在动态系统中非常有吸引力,因为它可以尽可能小且快速地实现。

AMS 提供了两套用于修改类文件的API。一种是基于事件模型,另一种是基于树形数据结构模型。这两个API可以简单理解为类似于XML API(SAX)和XML文档对象模型(DOM)。文档: 基于事件的API 类似于SAX,基于对象的API 类似于DOM。基于对象的API 构建在基于事件的基础上,例如SAX 可以提供的DOM。

基于事件的API 定义了一组可能的事件以及它们必须发生的顺序,提供了一个为每个元素生成事件解析器的类解析器,并从这些事件序列生成编译后的类。

基于树的数据结构API采用面向对象的设计,将类文件的结构映射到一组标准的树结构,以方便类文件的编辑。

从ASM 进一步衍生出几个工具,包括AspectJ 和CGLib 这两个著名的AOP 工具。

除了ASM之外,还有很多其他的字节码工具。以下是一些常用的字节码工具,供参考。

ASM http://由OW2 独立开源组织asm.ow2.org 提供。

Javassist http://jboss-javassist.github.io/javassist/由Jboss-javassist 维护

BCEL 由Apache 维护http://commons.apache.org/proper/commons-bcel/

ByteCode的技术原理和calss文件的使用涉及到三个阶段:编译、加载、执行。我们从这三个阶段总结原理和应用场景进行系统介绍。

编译字节码技术允许在非运行时对类文件进行修改和解析,因此原则上不需要在编译阶段引入太多对静态字节码的处理,但在应用程序中有很多例子。设想。

1. 代码分析

使用字节码的静态分析来计算指标、查找错误并检查代码中的编码约定

SemmleCode https://semmle.com SemmleCode 工程分析平台可帮助您快速识别和响应关键漏洞并开发安全、高质量的软件。

Sonargraph http://www.hello2morrow.com/products/sonargraph Sonargraph 是一款功能强大的静态代码分析器,可让您监控软件系统的技术质量,并在开发过程的各个阶段应用有关软件架构、指标和其他方面的规则。

TamiFlex http://secure-software-engineering.github.io/tamiflex/是一套工具,可帮助使用反射和自定义类加载器对Java 程序进行静态分析。

JCarder 是一个开源工具,用于检测并发多线程Java 程序中潜在的死锁。这是通过动态检测Java 字节码来完成的(即, 不是静态代码分析工具,而是在获取的锁图中查找循环)。

2. 代码生成

通过字节码修改生成代码,并将其与可插拔的注释处理API 相结合,以减少ORM 框架、EJB 框架、IOC 框架、JDO 框架、UnitTest 框架等的代码量。这里有很多知名的框架都使用了相关技术。此外,还有一些辅助编程工具等。

Spring核心技术结合AspectJ实现静态代理IOC框架。

Hibernate 使用字节码技术自动生成DO 类。

AgitarOne采用字节码技术自动生成测试类和测试代码。

Lombok 是一个通用的代码简化工具,它将注解与可插拔的注解处理API 结合起来,有效减少你编写的代码量,包括get、set、构造函数、哈希码和日志,所有这些都可以标记。

fun4j 是一个将函数式编程的主要概念集成到Java 平台中的框架。从本质上讲,它是一个lambda 到JVM 字节码编译器。

3. 语言扩展

类文件运行在JVM上,因此各种图灵完备的语言都可以编译成类文件并移植到JVM上。甚至为了解决一些特定的场景,您可以构建自己的领域语言(DSL)并将其编译成类文件来运行。 JVM上的其他主流语言包括:

Groovy、Scala、JRuby、Kotlin、Jython、NetRexx

类加载和运行时字节码技术简介本来我想分别介绍启动时和运行时使用的字节码技术,但是启动时和运行时这两种技术是联系在一起的,而且很多运行时技术都是基于启动时开发的。技术,所以将它们一起介绍。

仪器仪表

Java SE5向JVM提供了代理功能,支持JVM级别的AOP操作,以在类加载时替换和修改类文件。从Java SE 5 开始,您可以通过在常规Java 程序(具有main 函数的Java 类)中指定-javaagent 参数,使用java.lang.instrument.Instrumentation 接口在JVM 上实现拦截操作。用于启动检测代理程序的jar 文件(包含检测代理)。

Java SE 6 为检测包添加了更强大的功能,包括启动后检测、本机代码检测和动态更改类路径。这些变化意味着Java的动态控制和解释能力得到了增强,使得Java语言更加灵活多变。此外,本机插装也是Java SE 6 中的一项新功能,通过添加一个或一组前缀,Java SE 6 可以使以前无法实现的本机接口功能变得可能。最后,Java SE 6 Instrumentation 还添加了动态添加类路径的功能。所有这些新功能都改进了instrumentation包的功能,这反过来又使Java语言本身更加强大。

在Java SE 5中,仪器在运行之前必须使用命令行参数或系统参数配置其代理类。在实际操作中,虚拟机已经初始化(在大多数Java类库加载之前)并且仪器配置已经开始。虚拟机还配置有回调函数,用于检测特定类的加载并完成实际工作。然而,在许多现实情况下,启动虚拟机时无法配置代理,这实际上限制了仪器的应用。 Java SE 6 中的新功能改变了这一点。 Java Tools API 的Attach APT 方法允许您在执行过程中轻松动态配置加载代理类,以实现您的检测目标。

下图展示了javagent如何实现代理以及一些关键的内部方法。

附加API

Javaagent 可以在JVM 启动后加载。这是通过Attach API 完成的。当然,Attach API 不仅仅用于动态加载代理。 Attach API 实际上是一种用于JVM 进程间通信的工具,它允许您将特定指令从一个JVM 进程发送到另一个JVM 进程。加载javaagent 只是Attach API 发送的众多指令之一。诸如用于打印线程堆栈的jstack、用于列出Java 进程的jps 以及用于执行内存转储的jmap 等函数都是Attach API 可以发送的指令。

JVM 工具接口(JVMTI)

JVM 工具接口(JVMTI) 是JVM 提供的本机编程接口,允许开发人员监视状态并向JVM 执行指令。它的目的是开放一组JVM接口,用于分析、调试、监控、线程分析和代码。覆盖率分析和其他工具。

JVMTI 和Instrumentation API 具有非常相似的功能;两者都是一组用于操作和监视JVM 的接口,并且都必须由代理调用。

检测API必须打包成jar并通过Java代理(-javaagent)加载。

JVMTI 必须打包成动态链接库(包含在操作系统中,例如.dll/.so 文件)并通过JVMTI 代理(-agentlib/-agentpath)加载。

由于它们都是代理,因此它们也有两个加载时序:启动(Agent_OnLoad)和运行时附件(Agent_OnAttach)。

以下是您可以使用JVMTI 执行的操作:

获取所有线程、显示线程状态、显示线程调用堆栈、显示线程组、中断线程、显示持有和等待锁的线程、获取线程CPU 时间,甚至正在运行的方法您还可以强制它返回一个值.

您可以获得有关类、方法和字段、类详细信息、方法体字节码和行号的各种信息,将jar 添加到引导/系统类加载器,更改系统属性等。

遍历堆内存并检索对象、检索局部变量的值、监视成员变量的值……

各种事件的回调函数。加载类文件、引发和捕获异常、启动和终止线程、启动和终止临界区、修改成员变量、启动和终止GC、启动和终止方法调用、临界区争用和等待、VM 启动和停止.

设置和取消断点、监听断点进入事件、单步执行事件……

前面提到的instrumentation API也是基于JVMTI实现的。具体来说,在addTransformer的情况下,通过instrumentation注册的ClassFileTransformer实际上为类文件加载事件(ClassFileLoadHook)注册了一个JVMTI回调函数。

字节码技术在类加载和运行时的应用场景热部署领域

热部署的实现方式一般有两种。一种方法是使用ClassLoader 加载新类。但是,JVM 不允许您多次加载同一个类,因此您可能需要在加载之前卸载旧的类。顺便说一句,进程在执行过程中可能会丢失其状态或在短时间内变得不可用,这违背了热部署的一些初衷。另一种方法是通过javaagent修改内存中类的字节码或者拦截默认的加载器行为。这个方法有很多使用场景。请参阅《深入探索 Java 热部署》 http://www.importnew.com/17115.html。

JRebel:现在最常用的热部署工具是付费商业软件,这意味着它更加稳定和兼容。

Spring-Loaded:Spring的子项目,开源的热部署工具。

Hotcode2:阿里巴巴内部开发使用的热部署工具。功能与上面基本相同,但针对不同框架进行了许多改进。

IDE提供热插拔

当您在调试模式下启动Eclipse 或IntelliJ IDEA 时,默认情况下会启用热插拔功能。当用户在IDE中修改代码时,可以直接将其替换为目标程序中的类。但是,此功能仅允许您修改方法主体;它不允许您添加、删除或修改方法。 实现该功能与调试相关。

事实上,调试也是通过JVMTI代理来实现的。 JVITI 代理在调试连接期间加载到正在调试的JVM 中。调试器(IDE)通过JDI(Java调试接口)与被调试对象(目标Java程序)进行通信,设置断点并获取调试信息。除了这些调试功能之外,JDI 还提供了redefineClass 方法,允许您直接修改类的字节码。是的,我们实际上公开了JVMTI 的字节码检测功能,并且IDE 也将这个HotSwap 功能实现为调试器。

在线诊断领域

作为基本原理,Btrace 使用Java Agent + ASM + Java Instrumentation + Java Compiler API 在执行过程中动态调整和插入代码函数。 http://www.btrace.com

Grays的实现原理类似。参见阿里云文章《Greys Java在线问题诊断工具》 https://yq.aliyun.com/articles/2390。

Byteman Byteman 的原理是在运行时修改应用程序类的字节码http://byteman.jboss.org

代码覆盖率

JaCoCo JVM 通过使用-javaagent 参数指定特定的jar 文件来启动检测代理程序。代理在通过类加载器加载类之前,确定是否对类文件进行转换和修改,并向类中注入统计代码。测试覆盖率分析允许您在JVM 上运行测试。

应用程序性能监控(APM) 工具

目前市场上的大部分监控产品原理上都和JaCoco类似,前五个可用的工具是:APM Tools Collection https://dzone.com/articles/java-performance-monitoring。 -5- 你应该了解的开源工具

舞台监视器http://www.stagemonitor.org

精确定位https://github.com/naver/pinpoint

蚊子https://www.moskito.org

发光根https://glowroot.org

卡蒙http://kamon.io/documentation/get-started/

利用动态代理技术实现AOP

CGLIB 在Spring AOP 中,CGLIB 通常用于生成AopProxy 对象。 Hibernate中PO(Persistant Object)字节码的生成也依赖于此。 https://github.com/cglib/cglib/wiki

通过DynamicAspects 工具和javaanent 实现的动态代理http://dynamicaspects.sourceforge.net

参考资料JVM简介https://anturis.com/blog/java-virtual-machine-the-essential-guide/

JVM 内部人士http://blog.jamesdbloom.com/JVMInternals.html

JAVA 语言和JVM 规范https://docs.oracle.com/javase/specs/index.html

JVM 指令集https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokeinterface

ASM 用户http://asm.ow2.org/users.html

ASM4 手册http://download.forge.objectweb.org/asm/asm4-guide.pdf

CGLib 用户https://github.com/cglib/cglib/wiki

开源字节码工具http://www.java-source.net/open-source/bytecode-libraries

BCEL官方文档http://commons.apache.org/proper/commons-bcel/

javaagent https://www.jianshu.com/p/1557dc1b1094

JVMTI https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html

JVMTM 工具接口https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html

JVM源码分析之Javaagent原理完整解读http://www.infoq.com/cn/articles/javaagent-illusterated

JSR 199 Java 编译器API https://www.jcp.org/en/jsr/detail id=199

注释处理器API https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html

IBM Java SE 6 编译器API 的新增功能https://www.ibm.com/developerworks/cn/java/j-lo-jse64/index.html

JSR 269: 可插入注释处理API http://www.jcp.org/en/jsr/detail id=269

BTrace https://github.com/btraceio/btrace

BTrace简介https://www.jianshu.com/p/93e94b724476

IBM Java SE 6 中的新增功能检测中的新增功能https://www.ibm.com/developerworks/cn/java/j-lo-jse61/index.html

仪器包信息https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html

JCarder http://www.jcarder.org

AspectJ https://en.wikipedia.org/wiki/AspectJ

AspectJTM 编程指南http://www.eclipse.org/aspectj/doc/published/progguide/index.html

Java 性能监控: 您应该了解的5 个开源工具https://dzone.com/articles/java-performance-monitoring-5-open-source-tools-you-Should-kno

w
JVM Attach机制实现 http://lovestblog.cn/blog/2014/06/18/jvm-attach/
Attach API https://docs.oracle.com/javase/7/docs/technotes/guides/attach/
Attach API 标准 https://docs.oracle.com/javase/8/docs/jdk/api/attach/spec/
关于作者头条号:Java深度思考 的作者,现就职于支付宝金融核心技术部,任高级技术专家,花名丛英,技术爱好广泛喜欢,热爱Java技术,也爱研究现在流行的区块链和机器学习相关的内容;对于三方支付业务、金融技术架构、技术管理方面有比较丰富的经验。
欢迎大家关注的我的头条号,和我一起分享技术工程师热爱的话题。

本文和图片来自网络,不代表火豚游戏立场,如若侵权请联系我们删除:https://www.huotun.com/game/579947.html

(0)
上一篇 2024年5月25日
下一篇 2024年5月25日

相关推荐

  • 和平精英怎么救敌人? 和平精英怎么标点敌人位置?

    和平精英怎么救敌人? 和平精英救敌人需要做到以下几点:1. 保持和平:要在救敌人的过程中一直保持和平,把救人的优秀行为的扩散到现场。2. 尊重人权:在处理所有人的问题时,应该尊重他们的权利,遵守人权协议。3. 倡导和谐:表达对和平的赞赏,并倡导支持彼此的关系,尽力保持和谐的气氛。4.耐心劝导:深思熟虑,以理服人,努力说服敌人把他们的思想观念调整,用和平方式处…

    游戏快讯 2分钟前
  • 和平精英怎么飙车? 和平精英特训岛飙车路线?

    和平精英怎么飙车? 在和平精英中飙车需要先找到一辆可驾驶的车辆,然后走到车辆旁边按下“上车”按钮即可进入驾驶座位。驾驶档位和刹车油门控制使用手机屏幕上的虚拟摇杆即可。飙车时需要注意防止翻车撞车,并适时使用刹车,掌握好速度和车辆操作即可。 和平精英特训岛飙车路线? 特训岛有多种飙车路线可以选择。但总体来说,建议要掌握一些基本路线,比如从南侧的修理厂出发,橙色房…

    游戏快讯 1小时前
  • 和平精英怎么连续开枪?

    和平精英怎么连续开枪? 和平精英连发和自动模式都可以连续开枪 和平精英怎么无声开枪? 不能,就算没声地图也显示,无声脚步可以 和平精英电脑怎么开枪? 和平精英电脑版左键开枪,我们一般应用于鼠标的左键鼠标的左键对应着我们手指的食指,我们知道,我们右手的食指是最灵活的一个手指,所以说用这个手指来控制和平精英的开火,是最完美的因此,和平精英的左键开火是最好的,最灵…

    游戏快讯 2小时前
  • 和平精英典藏是什么? 和平精英典藏室怎么切换宠物?

    和平精英典藏是什么? 《关于和平精英典藏》对典藏来说这些东西都是限定的,而且是每日通过组队任务,并领取 (典藏称号)等奖励,典藏任务显示一个任务条(%100),任务条完成后在个人主页带上典藏风格,按照星星集满成就,而且每日都会赠送一把钥匙,完成一些赛季解锁成就 和平精英典藏室怎么切换宠物? 和平精英里没有典藏室怎么切换宠物。 和平精英更改宠物的方法: 点开背…

    游戏快讯 4小时前
  • 和平精英风声怎么关? 和平精英变声器怎么关?

    和平精英风声怎么关? 在设置把游戏音效关闭就没有风声了 和平精英变声器怎么关? 1.点击设置 2.从游戏中找到游戏设置选项并点击一下。 3.点击声音设置 4.在设置界面找到“声音设置”选项进入。 5.关闭变声器 6.在变声器栏下点击关闭按钮即可。 和平精英手机振动怎么关? 第一种:桌面下滑,然后搜索游戏(应用)助手,进入游戏助手,点击右上角—设置—关闭,找到…

    游戏快讯 5小时前