为什么学习jvm
如果你这辈子只甘心做一个平庸的Java码农,那么你可以利用阅读本文的时间去学习其他新的技术知识,但是如果你想成为一个更更更更优秀的中高级程序员!那么请继续阅读本文,希望这篇文章会对你有所帮助,那么学习jvm有啥好处嘞?
首先:
- 你能够明白为什么Java最早期被称为解释型语言,而后来为什么又被大家叫做解释与编译并存的语言(了解JVM中解释器以及即时编译器就可以回答这个问题);
- 你能够理解动态编译与静态编译的区别,以及动态编译相对于静态编译到底有什么好处(JVM JIT);
- 你能够利用一些工具,jmap, jvisualvm, jstat, jconsole等工具可以辅助你观察Java应用在运行时堆的布局情况,由此你可以通过调整JVM相关参数提高Java应用的性能;
- 可以清楚知道Java程序是如何执行的;
- 可以明白为什么Java等高级语言具有可移植性强的特性。
目录
什么是虚拟机
虚拟机概述
java虚拟机作用
Jvm组成
Jvm结构 -类加载
类加载子系统
类加载过程
类什么时候初始化
类初始化的顺序
类加载器分类
双亲委派机制
JVM运行时数据区
程序计数器
java虚拟机栈
栈的基本概念:
栈的特点:
栈运行原理:
栈帧的内部结构
本地方法栈(Native Method Stack)
java堆内存
堆内存概述
堆内存区域划分
为什么分区(代)?
对象创建内存分配过程
新生区与老年区配置比例
分代收集思想 Minor GC、Major GC、Full GC
堆空间的参数设置
字符串常量池
方法区
方法区的基本理解
方法区大小设置
方法区的内部结构
方法区的垃圾回收
本地方法接口
本地方法:
为什么要使用 Native Method
什么是虚拟机
虚拟机概述
- 所谓虚拟机(Virtual Machine),就是一台虚拟的计算机。它是一款软件,用来执行一系列虚拟计算机指令。大体上,虚拟机可以分为系统虚拟机和程序虚拟机。
- 大名鼎鼎的 VMware 就属于系统虚拟机,它是完全对物理计算机的仿真,提供了一个可运行完整操作系统的软件平台。程序虚拟机典型的代表就是 java虚拟机了,它专门为执行某个单个计算机程序而设计。在 java 虚拟机中执行的指令我们称为 java 字节码指令。
- Java 虚拟机是一种执行 java 字节码文件的虚拟计算机,它拥有独立的运行机制。
- Java 技术的核心就是 java 虚拟机,因为所有的 java 程序都运行在 java 虚拟机内部。
java虚拟机作用
- 一次编译到处运行
- 自动内存管理
- 自动垃圾回收功能
Jvm组成
1.类加载器(ClassLoader)2.运行时数据区(Runtime Data Area)3.执行引擎(Execution Engine)4.本地库接口(Native Interface)
Jvm结构 -类加载
类加载子系统
类加载过程
加载 --> 验证 --> 准备 --> 解析 --> 初始化
加载:
1. 通过类名(地址)获取此类的二进制字节流.2. 将这个字节流所代表的静态存储结构转换为方法区(元空间)的运行时结构.3. 在内存中生成一个代表这个类的 java.lang.Class 对象,作为这个类的各种数据的访问入口.
检验被加载的类是否有正确的内部结构,并和其他类协调一致;验证文件格式是否一致 : class 文件在文件开头有特定的文件标识(字节码文件都以 CA FE BA BE 标识开头 ),主、次版本号是否在当前 java 虚拟机接收范围内.元数据验证: 对字节码描述的信息进行语义分析,以保证其描述的信息符合java 语言规范的要求,例如这个类是否有父类;是否继承浏览不允许被继承的类(final 修饰的类)
准备阶段则负责为类的静态属性分配内存,并设置 默认初始值;不包含用 final 修饰的 static 常量,在编译时进行初始化.例如: public static int value = 123;value 在准备阶段后的初始值是 0,而不是 123.
解析:
将类的二进制数据中的符号引用替换成直接引用(符号引用是 Class 文件的逻辑符号,直接引用指向的方法区中某一个地址)
初始化:
为类的静态变量赋予正确的初始值,JVM 负责对类进行初始化,主要对类变量进行初始化。初始化阶段就是执行底层类构造器方法<clinit>()的过程。 此方法不需要定义,是 javac 编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来的。
类什么时候初始化
- 通过 new 关键字创建对象
- 访问类的静态变量,包括读取和更新
- 访问类的静态方法
- 对某个类进行反射操作
- 初始化子类会导致父类的的初始化
- 执行该类的 main 函数
类初始化的顺序
类加载器分类
双亲委派机制
JVM运行时数据区
java8虚拟机规定,java虚拟机所管理的内存将包括以下几个运行时数据区域:
- 程序计数器(Program Counter Register):是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。
- Java 虚拟机栈(Java Virtual Machine Stacks):描述的是 Java 方法执行的内存模型,每个方法在执行的同时都会创建一个线帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每个方法从调用直至执行完成的过程,都对应着一个线帧在虚拟机栈中入栈到出栈的过程。
- 本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的。
- Java 堆(Java Heap):是 Java 虚拟机中内存最大的一块,是被所有线程共享的,在虚拟机启动时候创建,Java 堆唯一的目的就是存放对象实例,几乎所有的对象实例都在这里分配内存.
- 方法区(Methed Area):用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。 方法区是很重要的系统资源,是硬盘和 CPU 的中间桥梁,承载着操作系统和应用程序的实时运行.
程序计数器
- 它是一块很小的内存空间,几乎可以忽略不计,也是运行速度最快的存储区域.
- 在 JVM 规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程生命周期保持一致.
- 程序计数器会存储当前线程正在执行的 Java 方法的 JVM 指令地址.
- 它是程序控制流的指示器,分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成.
- 它是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域
java虚拟机栈
栈的基本概念:
栈是运行时的单位,即栈解决程序的运行问题,即程序如何执行,或者说如何处 理数据。
栈的特点:
栈是一种快速有效的分配存储方式,访问速度仅次于程序计数器.JVM 直接对 java 栈的操作只有两个:调用方法入栈.执行结束后出栈. 对于栈来说不存在垃圾回收问题
栈运行原理:
- JVM 直接对 java 栈的操作只有两个,就是对栈帧的入栈和出栈,遵循先进后出/ 后进先出的原则.
- 在一条活动的线程中,一个时间点上,只会有一个活动栈.即只有当前在执行的方法的栈帧(栈顶)是有效地,这个栈帧被称为当前栈(Current Frame),与当前栈帧对应的方法称为当前方法(Current Method),定义这个方法的类称为当前类(Current Class).
- 执行引擎运行的所有字节码指令只针对当前栈帧进行操作.
- 如果在该方法中调用了其他方法,对应的新的栈帧就会被创建出来,放在栈的顶端,成为新的当前栈帧
栈帧的内部结构
操作数栈(Operand Stack)(或表达式栈):
栈最典型的一个应用就是用来对表达式求值。在一个线程执行方法的过程中,实际上就是不断执行语句的过程,而归根到底就是进行计算的过程。因此可以这么说,程序中的所有计算过程都是在借助于操作数栈来完成的。
动态链接(Dynamic Linking) (或指向运行时常量池的方法引用):
因为在方法执行的过程中有可能需要用到类中的常量,所以必须要有一个引用指向运行时常量。
方法返回地址(Retuen Address)(或方法正常退出或者异常退出的定义):
本地方法栈(Native Method Stack)
- Java 虚拟机栈管理 java 方法的调用,而本地方法栈用于管理本地方法的调用.
- 本地方法栈也是线程私有的.
- 允许被实现成固定或者是可动态扩展的内存大小.内存溢出方面也是相同的. (如果线程请求分配的栈容量超过本地方法栈允许的最大容量抛出 StackOverflowError.)
- 本地方法是用 C 语言写的.
- 它的具体做法是在 Native Method Stack 中登记 native 方法,在 Execution Engine 执行时加载本地方法库.
java堆内存
堆内存概述
- 一个 JVM 实例只存在一个堆内存,堆也是 Java 内存管理的核心区域。
- Java 堆区在 JVM 启动时的时候即被创建,其空间大小也就确定了,是 JVM 管理的最大一块内存空间.
- 堆内存的大小是可以调节。
例如: -Xms:10m(堆起始大小) -Xmx:30m(堆最大内存大小)一般情况可以将起始值和最大值设置为一致,这样会减少垃圾回收之后堆内存重新分配大小的次数,提高效率
- 《Java 虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但逻辑上它应该被视为连续的。
- 所有的线程共享 Java 堆,在这里还可以划分线程私有的缓冲区。
- 《Java 虚拟机规范》中对 Java 堆的描述是:所有的对象实例都应当在运行时分配在堆上。
- 在方法结束后,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除。
- 堆是 GC(Garbage Collection,垃圾收集器)执行垃圾回收的重点区域。
堆内存区域划分
java 8 及之后堆内存分为:新生区(新生代)+老年区(老年代)
新生区分为 Eden(伊甸园)区和 Survivor(幸存者)区
为什么分区(代)?
对象创建内存分配过程
为新对象分配内存是一件非常严谨和复杂的任务,JVM 的设计者们不仅需要考虑内存如何分配,在哪分配等问题,并且由于内存分配算法与内存回收算法密切相关,所以还需要考虑 GC 执行完内存回收后是否会在内存空间中产生内存碎片。
-XX:MaxTenuringThreshold=<N>在对象头中,它是由 4 位数据来对 GC 年龄进行保存的,所以最大值为 1111,即为 15。所以在对象的 GC 年龄达到 15 时,就会从新生代转到老年代。
public static void main(String[] args) {
List<Integer> list = new ArrayList();
while(true){
list.add(new Random().nextInt());
}
}
新生区与老年区配置比例
分代收集思想 Minor GC、Major GC、Full GC
整堆收集出现的情况:System.gc();时老年区空间不足方法区空间不足开发期间尽量避免整堆收集.
堆空间的参数设置
字符串常量池
public static void main(String[] args) {
String temp = "world";
for (int i = 0; i < Integer.MAX_VALUE; i++) {
String str = temp + temp;
temp = str;
str.intern();//将字符串存储到字符串常量池中
}
}
方法区
方法区的基本理解
- 方法区在 JVM 启动时被创建,并且它的实际的物理内存空间中和 Java 堆区一样都可以是不连续的.
- 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展.
- 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,
- 虚拟机同样会抛出内存溢出的错误
- 关闭 JVM 就会释放这个区域的内存.
方法区,栈,堆的交互关系:
方法区大小设置
Java 方法区的大小不必是固定的,JVM 可以根据应用的需要动态调整.
- 元数据区大小可以使用参数-XX:MetaspaceSize 和 -XX:MaxMataspaceSize 指定,替代上述原有的两个参数.
- 默认值依赖于平台,windows 下,-XXMetaspaceSize 是 21MB,
- -XX:MaxMetaspaceSize 的值是-1,级没有限制.
- 这个-XX:MetaspaceSize 初始值是 21M 也称为高水位线 一旦触及就会触发 Full GC.
- 因此为了减少 FullGC 那么这个-XX:MetaspaceSize 可以设置一个较高的值
方法区的内部结构
方法区的垃圾回收
本地方法接口
本地方法:
什么是本地方法?简单来讲, 一个 Native Method 就是一个 java 调用非 java 代码的接口 ,一个 Native Method 是这样一个 java 方法:该方法的底层实现由非 Java 语言实现, 比如 C。这个特征并非 java 特有,很多其他的编程语言都有这一机制在定义一个 native method 时,并不提供实现体(有些像定义一个 Java interface),因为其实现体是由非 java 语言在外面实现的。 关键字 native 可以与其他所有的 java 标识符连用,但是 abstract 除外。
为什么要使用 Native Method
下半篇传送门:戳链接进去 文章来源:https://www.toymoban.com/news/detail-435829.html
Jvm --java虚拟机(下)_CsDn.FF的博客-CSDN博客1.执行引擎是 Java 虚拟机核心的组成部分之一。2.JVM 的主要任务是负责装载字节码到其内部,但字节码并不能够直接运行在操作系统之上,因为字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被 JVM 所识别的字节码指令、符号表,以及其他辅助信息。3.那么,如果想要让一个 Java 程序运行起来,执行引擎(Execution Engine)的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,JVM 中的执行引擎充当了将高级语言翻译为机器语言的译者。https://blog.csdn.net/weixin_56800176/article/details/130587453 文章来源地址https://www.toymoban.com/news/detail-435829.html
到了这里,关于Jvm --java虚拟机(上)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!