大家都知道,java号称一次编译,处处运行。之所以能够这么强大,jvm功不可没。直接上图:
笔者看过这张图很多次,一直没能理解。一直到最近,觉得能够明白到写博客了。一个java文件通过编译可以得到class文件,class文件就是java虚拟机能够执行的二进制文件。而程序在运行的时候,需要在内存中有数据空间。在jvm中,这个数据空间叫做运行时数据区。运行时数据区,一共有5类空间,分别是:方法区,堆区,java栈,PC寄存器(我更喜欢叫程序计数器,jvm中没有寄存器)以及本地方法栈。
当jvm运行的时候,会先把class文件以二进制数据流的形式加载到方法区,这个过程通过类加载器系统完成(之所以叫做类加载器系统,是因为类加载器可以不只有一个,但常用的是启动类加载器)。一个个说吧!
方法区存储的是类的元数据,包括类的名称,超类等等元数据信息。这些信息中有3个比较重要的:
1 类的常量池
2 一个到当前类的Class类对象的引用
3 一个到当前类的ClassLoader类对象的引用
对于第二个,我想用过java反射机制的都应该明白了他的设计。在java反射机制中,通过Class.forName()等几种方法可以得到特定类的对象。对于第三个,用于记录装载当前类的类装载器对象。对于第一个,这里想重点说下:
jvm为每一个被装载的类都维护一个常量池,这个常量池包含了直接常量和对其他类型,字段和方法的符号引用。其中,直接常量很好理解,比如String str="hello";那么str就是一个直接常量。什么是符号引用呢?比如MyClass mc=new MyClass();当类装载器装载这条语句所在类的时候,就会在常量池中记录MyClass xxx.xxx.MyClass,这个就叫做类型的符号引用,当然还有字段的符号引用,方法的符号引用等等。因为常量池中包含了当前类所用到的所有的符号引用(符号引用之后会变成直接引用),所以他在java程序的动态连接中有很重要的位置。
有些时候,为了提高jvm的性能,可能方法区会包含除了上述数据以外的其他数据,比如方法表:jvm对每个装载的非抽象类,都生成一个方法表,把他作为类信息的一部分存储在方法区。这样,以后再查找类方法时就不需要读取类信息,而是根据方法表直接访问。
当类装载器将class文件装载到了方法区,执行引擎就开启从指定类的public static void main()方法执行了,执行过程中会产生对象实例,
这些对象实例存储在堆区。我们知道,在类的对象中,对象的数据是属于对象的,但对象的方法是调用类的方法,因此堆区中的类对象需要“记得”自己在方法区的类方法。因此,对于堆区的设计,可以是下面几种方案:
上面的几种方案就不具体说了,很容易理解。对于堆区,还有个很重要的事情,就是垃圾回收,我们知道垃圾回收是java的一大特色,垃圾回收主要的作用空间就是堆区。关于垃圾回收,以后再说。关于堆区和方法区,下面举个例子:
对于下面的代码,我们来看他的执行过程。
public class A{
private int speed;
public void set(){
speed=4;
}
}
public class B{
public static void main(String [] args){
A a=new A();
a.set();
}
}
当运行java B的时候,执行过程如下:首先类装载器加载类B到方法区(其中在常量池中有A的符号引用),接着执行第一行命令,看到使用new关键字,执行引擎需要在堆区新建一个A的对象空间。执行引擎查看B的常量池,发现对A存储的只是一个符号引用,不是直接引用。因此可能需要装载类A到方法区,装载完毕后,返回一个方法区类A的指针引用给类B的常量池(以后类B的常量池可以直接通过引用找到类A)。之后,由于类B知道了类A的详细信息,执行引擎就可以在堆区分配一个类A的实例对象,并将改对象的引用压如到当前线程的java栈中。第一条命令执行结束。
接着说其他三个区域。java栈,程序计数器,本地方法栈(不一定每个线程都有)对应一个线程。就是说,jvm每有一个线程被创建,就会为这个线程对应一个java栈和程序计数器(本地方法栈看是否需要)。由于java栈是线程独有,因此不存在同步问题。与此相对,方法区和堆区都是所有线程共享的区域(从代码角度很容易理解),因此存在线程安全问题。下图能够说明这一点:
java栈是线程执行过程中存放局部变量,操作数等信息的空间,他的基本单位是帧。java栈对应的线程每执行一个方法,就会向栈中压如一个栈帧。这个栈帧包括局部变量区,操作数栈和帧数据区。
PC寄存器实际上是程序计数器,用来记录当前线程要执行的下一条指令是什么。
当一个线程在执行过程中需要调用本地方法时,就会创建一个本地方法栈功本地方法使用。
至此,大概介绍了下jvm的基本结构以及他的运行时数据区的基本功能。
- 大小: 129.5 KB
- 大小: 65.8 KB
- 大小: 65.5 KB
- 大小: 92.8 KB
- 大小: 20.5 KB
分享到:
相关推荐
是生态体系下的重要模块,它具备了JVM-Sandbox的所有特点,插件式设计便于快速适配各种中间件,封装请求录制/回放基础协议,也提供了通用可扩展的各种丰富API。 目标人群 - 面向测试开发工程师 线上有个用户请求一直...
#### 二、JVM体系结构概览 JVM启动后,在操作系统层面表现为一个独立的进程,其内部架构包括以下几个关键组成部分: ##### 2.1 类装载器(ClassLoader) 类装载器负责加载Java类文件(.class文件)。这些文件包含...
**小菜鸟系列-JVM体系结构** Java虚拟机(JVM)是Java平台的核心组成部分,它为Java程序提供了跨平台的运行环境。理解JVM的体系结构对于优化代码性能、排查故障以及深入理解Java编程至关重要。在本文中,我们将探讨...
JVM内存结构-JVM体系结构 程序计数器 虚拟机栈 本地方法栈 堆 方法区
JVM体系结构与GC调优相关介绍,包含JVM体系结构、常用GC算法、内存管理、垃圾回收器、虚拟机调优、相关监控工具等
JVM 与 Java 体系架构 本系列博客主要是面向 Java 8 的虚拟机,主要参考尚硅谷的 JVM 视频教程,整理不易,所以图片打上了一些水印,还请读者见谅。后续可能会加上一些补充的东西。 在学习 JVM 之前,我们首先需要...
JVM与Java体系结构
jvm体系结构与GC调优,图文齐飞,方便理解,,非常适合入门的java工程师以及性能测试工程师阅读,欢迎大家下载
自己总结的jvm中jvm与java体系结构新特性的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。适合jvm的爱好者和学习者
"JVM详解-淘宝内部资料"提供了一套深入理解JVM的资源,涵盖了从基础到高级的各种主题,包括Java虚拟机的生命周期、JVM的体系结构、各个组件的详细解析以及垃圾收集(Garbage Collection, GC)机制等内容。...
综上所述,JVM体系结构是Java语言跨平台运行的核心。了解JVM的工作机制有助于开发出更加健壮和高效的Java程序。JVM类加载机制、内存管理、执行引擎等知识点,对于性能调优和故障排除也至关重要。通过掌握这些知识点...
JVM体系结构与GC调优
JVM体系结构与GC调优