JVM学习-JVM简介以及其内部结构

目录

1.什么是JVM

2.JVM、JRE、JDK、JavaSE、JavaEE之间的联系

3.JVM的内部结构

4.各部分的作用

[4.1 类加载器](#4.1 类加载器)

[4.2 方法区](#4.2 方法区)

[4.3 堆](#4.3 堆)

[4.4 虚拟机栈](#4.4 虚拟机栈)

[4.5 程序计数器](#4.5 程序计数器)

[4.6 本地方法栈](#4.6 本地方法栈)

[4.7 解释器和JIT即时编译器](#4.7 解释器和JIT即时编译器)

[4.9 GC垃圾回收](#4.9 GC垃圾回收)

5.拓展

5.1一些可能会遇到的问题

5.2堆内存溢出诊断方法

5.3linux环境下线程诊断方法


1.什么是JVM

JVM是Java虚拟机的缩写,是Java程序的运行环境。更准确地说是Java程序的二进制字节码的运行环境,因为JVM的主要作用是将Java源码编译为字节码并执行。Java程序之所以能够跨平台运行就是因为JVM的存在,JVM编译后的字节码在任何支持JVM的平台都可以运行且无需再次编译;并且JVM有自己的垃圾回收机制,自动管理内存,减轻了程序员内存管理的负担。

通过学习JVM,我们就可以了解一个Java程序在底层的执行过程,进而优化我们的代码。

2.JVM、JRE、JDK、JavaSE、JavaEE之间的联系

3.JVM的内部结构

4.各部分的作用

4.1 类加载器

用来加载类的二进制字节码(包括类的基本信息、常量池,类方法定义)。有四种类加载器:启动类加载器、扩展类加载器、应用类加载器、自定义类加载器。

4.2 方法区

方法区是线程共享的一块区域,存储了和类结构相关的信息,比如运行时常量池、成员变量、方法数据等;方法区在虚拟机启动时被创建,逻辑上是堆的一部分。之所以说逻辑上是堆的一部分是因为实际的存储位置并不一定在堆中,比如Hotspot(JVM的一种)的jdk1.8版本是将方法区放在了元空间,而元空间使用的是操作系统的一部分内存;jdk1.6版本的则放在了永久代中,永久代使用的是堆内存。方法区也会触发垃圾回收,当大量的类被加载时会导致方法区空间不足。要注意的是,在JDK1.7版本前方法区空间不足触发的异常是内存不足:永久代(java.lang.OutOfMemoryError: PermGen space),在JDK1.8版本后则是内存不足:元空间(java.lang.OutOfMemoryError: Metaspace)

4.3 堆

堆是线程共享的,所有通过new创建的对象都会存放在堆中。当存储的对象过多或者串池存放的值过多时会导致堆内存溢出,也就会触发垃圾回收。如果垃圾回收后堆内存仍不足,那就是其中的对象大部分都还在被使用无法回收,内存占用仍然很高。要注意的是,在JDK1.6版本前串池空间不足触发的异常是内存不足:永久代(java.lang.OutOfMemoryError: PermGen space),而JDK1.7版本后提示的异常则是内存不足:堆空间(java.lang.OutOfMemoryError: Java heap space)

4.4 虚拟机栈

每个线程在创建时都会创建一个虚拟机栈,这是线程运行所需要的内存,所以虚拟机栈是线程私有的。每个栈中存放一个个栈帧,栈帧则是调用一个方法所需要的内存,里面存放着局部变量表、操作数栈、返回地址等;栈帧中仅有一个活动栈帧,对应当前正在执行的方法,也是栈顶的栈帧,如果当前方法调用了其他方法,那么对应的新的栈帧会被创建出来,放在栈的顶端成为新的活动栈帧。当方法执行完成或者抛出异常自动结束执行时,均作为执行完毕处理,就会将该方法对应的栈帧弹出虚拟机栈,活动栈帧自然就会变成下一个方法对应的栈帧。

虚拟机栈不会触发垃圾回收,因为方法执行完后栈帧就被弹出去了,不会留在栈中。但存在栈内存溢出的问题,一种是栈帧过多导致的,比如无限递归;另一种是栈帧过大导致的,一般都是由栈帧过多引起的栈内存溢出,因为普通情况下执行一个方法所用到的局部变量不是很多,栈帧也不会太大。

虚拟机栈由于栈帧中的局部变量都是线程私有的,所以只要不逃离线程的作用范围就不会产生线程安全问题;但堆是线程共享的,所以都需要考虑线程安全问题。

4.5 程序计数器

主要作用就是记住下一条JVM指令的执行地址,以在执行完当前的一个JVM指令后能够找到下一个指令,实际上是一个寄存器,每个线程只有一个程序计数器,且程序计数器是线程私有的,不存在内存溢出的问题。

4.6 本地方法栈

本地方法栈是线程私有的,随着线程的结束而消失,所以不会触发垃圾回收。

4.7 解释器和JIT即时编译器

4.9 GC垃圾回收

当堆内存不足时就会出发垃圾回收,堆中存放对象的地方又分为新生代和老年代, 新生代又分为伊甸园和幸存区,幸存区分为from和to两部分。一般情况下,新产生的对象被放在伊甸园中,执行垃圾回收时没有被回收的对象会放到幸存区中,如果这些对象在执行多次垃圾回收时依旧没有被回收,那么就会将这些对象从幸存区放到老年代中。

详细内容见另一篇博客:JVM学习-垃圾回收专题

5.拓展

5.1一些可能会遇到的问题

5.2堆内存溢出诊断方法

5.3linux环境下线程诊断方法

相关推荐
Amarantine、沐风倩✨29 分钟前
设计一个监控摄像头物联网IOT(webRTC、音视频、文件存储)
java·物联网·音视频·webrtc·html5·视频编解码·七牛云存储
机智的叉烧1 小时前
前沿重器[57] | sigir24:大模型推荐系统的文本ID对齐学习
人工智能·学习·机器学习
路在脚下@1 小时前
spring boot的配置文件属性注入到类的静态属性
java·spring boot·sql
森屿Serien2 小时前
Spring Boot常用注解
java·spring boot·后端
量子-Alex2 小时前
【多模态聚类】用于无标记视频自监督学习的多模态聚类网络
学习·音视频·聚类
吉大一菜鸡2 小时前
FPGA学习(基于小梅哥Xilinx FPGA)学习笔记
笔记·学习·fpga开发
苹果醋33 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader3 小时前
深入解析 Apache APISIX
java·apache
菠萝蚊鸭3 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪4 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word