【精通 JVM 原理】浅析 JavaAgent & Instrumentation 机制

浅析 JavaAgent & Instrumentation 机制

前言

本文主要内容

1、JVM的字节码指令,方法调用机制
2、Java类加载器
3、JavaAgent
4、Java Instrumentation

词汇说明

Java Virtual Machine (JVM)

什么是字节码?

机器码

机器码(machine code)是CPU可直接解读的指令。机器码与硬件等有关,不同的CPU架构支持的硬件码也不相同。

字节码

字节码(bytecode)是一种包含执行程序、由一序列 op 代码/数据对 组成的二进制文件。字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。通常情况下它是已经经过编译,但与特定机器码无关。字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。

字节码的实现方式是通过编译器和虚拟机器。编译器将源码编译成字节码,特定平台上的虚拟机器将字节码转译为可以直接执行的指令。

例如:C# IL,Java bytecode

JVM字节码执行模型及字节码指令集:https://blog.csdn.net/lijingyao8206/article/details/46562933

JVM 虚拟机字节码指令表:https://segmentfault.com/a/1190000008722128

Java 源代码的编译和执行

Java 源代码的编译过程如下图:

JVM的运行时数据区的结构如下图:

字节码指令执行的数据结构是栈帧(Stack Frame),也就是在虚拟机栈中的栈元素。

JVM 虚拟机会为每个方法分配一个栈帧,因为虚拟机栈是LIFO(后进先出)的,所以当前线程正在活动的栈帧,也就是栈顶的栈帧,JVM规范中称之为“CurrentFrame”, 这个当前栈帧对应的方法就是“CurrentMethod”。

字节码的执行操作,指的就是对当前栈帧数据结构进行的操作。

桢栈的数据结构

一个JVM 进程在操作系统中的全局图如下:

讲到数据结构,就必须要看内存模型。

JVM 内存模型与运行时数据区

JVM运行时数据区包括:PC寄存器,JVM栈,本地方法栈,堆,方法区几个部分。

看图说话:

Java Class File 字节码文件,通过“Class Loader”加载到 “Runtime Data Area” 中,然后交给 “Execution Engine” 执行。

JVM 内存分配过程:

JVM运行时数据区图示: Memories of a Java Runtime

JVM runtime memory

Class Method Area

Once a class bytecode is loaded by a JVM class loader, it’s passed to the JVM for further processing.

The JVM creates an internal representation of the class and stores it in the method area.

An example of a class method area is shown in above Figure. The following data areas are contained within the internal representation of a class:

  • Runtime Constant Pool contains constants used in a particular class. The constants can be of types int, float, double, and UTF-8. It also contains references to methods and fields.

  • Method Code is the implementation (opcodes) of all class methods.

  • Attribute and Field Values contain all named attributes and field values of a class. A field value points to a value stored in the runtime constant pool.

JVM Stack

每个栈帧对应着一个未运行完的函数,栈帧中保存了该函数的返回地址和局部变量。

栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。从逻辑上讲,栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等。

栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。

Every thread has a private JVM stack. A stack is created during a thread startup time and its size can be static or dynamic. A JVM stack is used for storing stack frames as shown in Figure:

A new stack frame is created and pushed into a thread stack every time a method is invoked. A frame is popped when a method returns.

Though there may be multiple frames on a stack from nested method calls, only one frame is active at a given time for a thread.

A JVM throws a StackOverflowError when a thread needs a stack area larger than permitted or memory available. If a JVM stack is dynamically allocated, a JVM may throw an OutofMemoryError if insufficient memory is available to meet stack size increase request. It may also throw a OutofMemoryError if insufficient memory is available during initial stack allocation.

Java 方法调用执行机制

JavaAgent

Java Instrumentation

参考资料

https://indrabasak.github.io/java-runtime-memory/https://blog.csdn.net/poiuyds/article/details/81196916

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光剑书架上的书

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值