JVM知识点汇总_被迫流浪者的博客
来源:http://www.tudoupe.com时间:2022-02-08
JVM知识点汇总
- 参考
- JVM简介
- JVM的位置
- JVM的体系结构
- 方法区
- 常量池
- 堆(针对JVM:HotSpot)
- GC常用算法
- 栈的一些补充
- Java栈
- 本地方法栈
- 程序计数器
- 类加载器
- 作用:
- 分类:
- 图示:
- 加载机制:双亲委派机制
- 沙箱安全机制
- Java对象在内存中实例化的过程
参考
- https://blog.csdn.net/qq_30336433/article/details/83268945
- https://blog.csdn.net/Tony__Jaa/article/details/107612059
- https://zhuanlan.zhihu.com/p/102171664
- https://www.cnblogs.com/sunfie/p/5125283.html
JVM简介
- JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。
- 引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
JVM的位置

JVM的体系结构

- 方法区:存储运行时常量池、已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
- 堆:存储实例对象
- java栈:也叫虚拟机栈,存放方法运行时所需的数据成为栈帧
- 本地方法栈:JVM调用本地方法(服务的对象是JVM执行的native方法,其就是一个java调用非java代码的接口,作用是与操作系统和外部环境交互)
- 程序计数器:记录当前线程所执行到的字节码的行号
方法区
- 方法区是被线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说所有定义方法的信息都保存在该区域
- 存储静态变量、常量、类信息(构造方法、接口定义)、运行时的常量池
- (在JDK1.7发布的HotSpot中,已经把字符串常量池移除方法区了)
常量池
- 运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放
- Java虚拟机对class文件每一部分的格式都有严格规定,每一个字节用于存储哪种数据都必须符合规范才会被jvm认可。但对于运行时常量池,Java虚拟机规范没做任何细节要求
- 运行时常量池有个重要特性是动态性,Java语言不要求常量一定只在编译期才能产生,也就是并非预置入class文件中常量池的内容才能进入方法区的运行时常量池,运行期间也有可能将新的常量放入池中,这种特性使用最多的是String类的intern()方法
- 既然运行时常量池是方法区的一部分,自然受到方法区内存的限制。当常量池无法再申请到内存时会抛出outOfMemeryError异常
堆(针对JVM:HotSpot)
参考: 一文带你了解JVM堆详解
- 一个JVM只有一个堆内存,堆内存的大小是可以调节的
- 堆内存细分为三个区域
- 新生代(对象存活率低,使用复制算法)
- 老年代(区域大,存活率高,使用标记清除法+标记整理法混合实现)
- 永久代
- JVM在进行垃圾回收(GC)时,并不是对这三个区域统一回收,大部分时候都是回收新生代
- GC的两种类型:轻GC(MinorGC)、重GC(FullGC)
GC常用算法
- 引用计数法
- 标记清除法
- 复制算法
- 标记整理法
参考: JVM学习之GC常用算法
思考:有没有最优的GC算法?
答案:没有最好的算法,只有最合适的算法---------》GC:分代收集算法
栈的一些补充
- 程序=数据结构+算法
- 栈:先进后出(First Input Last Output)
- 队列:先进先出(First Input First Output)
- 思考:为什么main()先执行,最后结束?
因为main()方法最先入栈,最后出栈
- 栈内存主管程序的运行,生命周期和线程同步;线程结束,栈内存也就释放,对于栈来说不存在垃圾回收问题
Java栈
- 线程私有,生命周期和线程相同,java栈描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧 用于存储局部变量表,操作数栈,动态链接,方法出口等信息;每个方法从调用直至完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程
- 局部变量表存放了编译期可知的各种基本类型数据(boolean、byte、char、short、int、float、long、double)、对象引用、returnAddress类型(指向了一条字节码指令的地址)
- 其中64位长度的long和double类型的数据会占用2个局部变量表空间(slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期完成分配,当进入一个方法时,这个方法所需要在栈帧中分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小
- 在Java虚拟机规范中,对此区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出Stack OverflowError异常;如果虚拟机栈可以动态扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常
本地方法栈
本地方法栈与java栈所发挥的作用非常相似,他们之间的区别不过是java栈为虚拟机执行Java方法(字节码)服务,而本地方法栈则为虚拟机中使用到的native方法服务。在虚拟机规范中对本地方法栈中方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机直接把本地方法栈和java栈合二为一,与java栈一样也会抛出Stack OverflowError异常和OutOfMemoryError异常
- native:凡是带native关键字的方法,说明java的作用范围达不到了,会去调用底层非java语言的库,会进入本地方法栈
- 本地方法栈会调用本地方法接口(JNI:Java Native Interface)
- JNI作用:扩展java的使用,融合不同的编程语言为java所用;最初:c、c++
- java诞生的时候,c、c++横行,想要立足,必须要有调用c、c++的程序
- 本地方法栈就是java在内存中专门开辟的一块标记区域,用来登记native方法
- 最终执行native方法,通过JNI加载本地方法库中的方法
- native使用场景:与硬件有关的功能,比如java程序驱动打印机、管理系统
程序计数器
- 即PC寄存器(Program Counter Register)
- 占据一块较小的内存空间,可以看做当前线程所执行的字节码的行号指示器。在虚拟机概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成
- 由于jvm的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,在任何一个确定的时刻,一个处理器都只会执行一条线程中的指令。因此未来线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存
- 如果线程正在执行的是一个Java方法,这个计数器记录的则是正在执行的虚拟机字节码指令的地址
- 如果正在执行的是Native方法,这个计数器则为空(undefined)
- 此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域
类加载器
作用:
加载class文件
分类:
- 虚拟机自带的加载器
- 启动类(根)加载器 :这个加载器不是一个Java类,而是由底层的c++实现,负责将存放在JAVA_HOME下lib目录中的类库,比如rt.jar。因此,启动类加载器不属于Java类库,无法被Java程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给启动类加载器,那直接使用null代替即可。
- 扩展类加载器:负责加载JAVA_HOME下libext目录下的,或者被java.ext.dirs系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加载器。
- 应用类加载器:由于这个类加载器是ClassLoader中的getSystemClassLoader方法的返回值,所以也叫系统类加载器。它负责加载用户类路径上所指定的类库,可以被直接使用。如果未自定义类加载器,默认为该类加载器。
图示:

加载机制:双亲委派机制
- 定义:当一个类加载器接收到类加载请求时,会先请求其父类加载器加载,依次递归,当父类加载器无法找到该类时(根据类的全限定名称),子类加载器才会尝试去加载。
- 作用:
- 从最内层JVM自带类加载器开始加载,外层恶意同名类得不到加载从而无法使用;
- 由于严格通过包来区分了访问域,外层恶意的类通过内置代码也无法获得权限访问到内层类,破坏代码就自然无法生效。
- 图示

沙箱安全机制
参考: java中的安全模型(沙箱机制)
Java对象在内存中实例化的过程
参考: Java对象在内存中实例化的过程
下一篇:没有了
相关新闻
- 2022-02-07 tomcat常见异常,tomcat解压后的目录
- 2022-02-07 surface+laptop2玩游戏
- 2022-02-07 【值得阅读的Mysql事务学习笔记】
- 2022-02-07 wsl备份与还原
- 2022-02-07 win11退回win10一直黑屏转圈怎么办
- 2022-02-07 C#-Hook钩子实例
- 2022-02-07 电脑自定义鼠标箭头
- 2022-02-07 电脑鼠标箭头不见了
- 2022-02-07 Android 调试桥 (adb)
- 2022-02-07 opencv环境搭建笔记
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
