【JVM】内存模型全面解读

简介: 【JVM】内存模型全面解读

根据JVM规范,JVM 内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。为了方便培养大家的全局观,本文从java文件编译开始介绍

本文基于jdk1.8,其他版本的介绍文中会有标明

Java内存模型

  • 线程私有:虚拟机栈,本地方法栈,程序计数器
  • 线程共享:堆,方法区,直接内存

1. java文件编译成Class文件

编译过程

从javac的代码的总体结构来看,编译过程大致分为1个准备过程和3个处理过程

  1. 准备过程:初始化插入式注解处理器
  2. 解析和填充符号表过程,包括:词法语法分析,将源代码的字符流转变成标记集合,构造出抽象语法树,填充符号表。产生符号地址和符号信息
  3. 插入式注解处理器的注解处理过程
  4. 分析与字节码生成过程
    a:标注检查。对语法的静态信息进行检查
    b:数据流及控制流分析,对程序动态运行过程进行检查
    c:解语法糖。将简化代码编写的语法糖还原为原有的格式
    d:字节码生成。将前面代码编写的语法糖还原为原有的格式

编译做了什么

1.常量

2.静态变量

3.静态常量

1.1 jvm有多少中常量池

一提到常量池就头疼,到底有多少常量池呢?位置在哪?都有什么作用?目前查资料了解到的有:Class文件常量池、运行时常量池,全局字符串常量池,以及基本类型包装类对象常量池

Class文件常量池

class文件中有一项是constant_pool(常量池),里面主要存放两大类常量:字面量(Literal)和符号引用(Symbolic References)。

字面量如:文本字符串、final常量值,

举个例子:string a="abc"中,"abc"就是字面量

符号引用包含下面三类:

  • 类和接口的全限定名
  • 字段的名称和描述符
  • 方法的名称和描述符

运行时常量池

是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,Java语言并不要求常量一定只有编译期才能产生,运行时也可以增加常量。

全局字符串常量池

从jdk7开始,方法区中的字符串常量池移到了Java堆中,这也意味着字符串常量池是所有线程共享的,JVM做的一个优化就是字符串常量池的常量是唯一的。

举个例子:下面这个代码创建了几个对象

String a=new String ("abc")

回答:可能是一个,也可能是两个,因为String的构造函数,JVM会先去字符串常量池去找"abc",如果有就不再创建,根据new命令会去堆中创建一个String对象,所以是一个;如果字符串常量池中没有,就会在常量池中创建一个,堆中创建一个,一共创建了2个。

再深入分析一下,(==如果只基本类型比较就是比较值,如果是对象就是比较地址)

上图中,s1==s2值为false,印证了 s1指向的是堆中的String对象,s2指向的是字符串常量池中的String对象,s3也是指向字符串常量池中的String对象。

基本类型包装类对象常量池

2. 类加载子系统加载.Class文件(类加载机制)

类加载机制:https://blog.csdn.net/yujing1314/article/details/105935391

双亲委派机制:https://blog.csdn.net/yujing1314/article/details/105838620

3. 运行时数据区

3.1 堆

堆的内存分配

简述

堆分为新生代和老年代,比例为1:2,新生代又分为伊甸园区,幸存者0区和幸存者1区

主要存储

JVM百分之95的对象都存在于堆中,所以垃圾回收算法主要针对的也是堆区

垃圾回收器

新生代的垃圾回收算法有Serial、Parnew等

老年代的垃圾回收器有CMS、PS等

垃圾回收算法

新生代的垃圾回收算法:标记-复制

老年代的垃圾回收算法:标记清除、标记整理

3.2 方法区

方法区是一种规范,1.7之前的实现是永久带,因为永久带容易导致内存溢出,1.7以后就去掉了永久带,将方法区的实现移到了元空间之中

3.3 虚拟机栈

栈是由栈帧组成的,一个栈帧中存了局部变量表、操作数栈、动态链接、方法返回地址

3.4 程序计数器

程序计数器中储存了下一条指令的地址

3.5 本地方法栈

本地方法栈主要是针对本地方法的

目录
相关文章
|
2天前
|
存储 Java C++
Java虚拟机(JVM)在执行Java程序时,会将其管理的内存划分为几个不同的区域
【6月更文挑战第24天】Java JVM管理内存分7区:程序计数器记录线程执行位置;虚拟机栈处理方法调用,每个线程有独立栈;本地方法栈服务native方法;Java堆存储所有对象实例,垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息;运行时常量池存储常量;直接内存不属于JVM规范,通过`java.nio`手动管理,不受GC直接影响。
14 5
|
17小时前
|
存储 Java 对象存储
jvm内存模型剖析
当线程cpu时间片执行完后,线程进入休眠状态,当再次唤醒时,通过程序计数器确定指令执行到哪一行,然后继续往下执行。
10 1
|
2天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
10 2
|
6天前
|
监控 算法 Java
Java虚拟机(JVM)使用多种垃圾回收算法来管理内存,以确保程序运行时不会因为内存不足而崩溃。
【6月更文挑战第20天】Java JVM运用多种GC算法,如标记-清除、复制、标记-压缩、分代收集、增量收集、并行收集和并发标记,以自动化内存管理,防止因内存耗尽导致的程序崩溃。这些算法各有优劣,适应不同的性能和资源需求。垃圾回收旨在避免手动内存管理,简化编程。当遇到内存泄漏,可以借助VisualVM、JConsole或MAT等工具监测内存、生成堆转储,分析引用链并定位泄漏源,从而解决问题。
17 4
|
8天前
|
算法 Java
Java垃圾回收(Garbage Collection,GC)是Java虚拟机(JVM)的一种自动内存管理机制,用于在运行时自动回收不再使用的对象所占的内存空间
【6月更文挑战第18天】Java的GC自动回收内存,包括标记清除(产生碎片)、复制(效率低)、标记整理(兼顾连续性与效率)和分代收集(区分新生代和老年代,用不同算法优化)等策略。现代JVM通常采用分代收集,以平衡性能和内存利用率。
34 3
|
13天前
|
算法 安全 Java
JVM系列4-垃圾收集器与内存分配策略(二)
JVM系列4-垃圾收集器与内存分配策略(二)
20 0
JVM系列4-垃圾收集器与内存分配策略(二)
|
19天前
|
存储 Java
JVM内存结构(4)
JVM内存结构
18 1
|
17小时前
|
存储 缓存 算法
JVM对象创建与内存分配机制
该类对应的java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
5 0
|
23小时前
|
存储 安全 Java
JVM之内存结构
Java内存结构包括程序计数器、虚拟机栈、本地方法栈、堆和直接内存。程序计数器记录执行地址,线程私有,无溢出。虚拟机栈处理方法调用,局部变量在线程栈中,过深或过大可能导致StackOverflowError。本地方法栈服务于native方法。堆存储对象,线程共享,有垃圾回收。方法区存储类信息,1.8前的永久代,1.8后的元空间,溢出可调整相应参数。运行时常量池包含字符串池,1.6在永久代,1.8在堆,intern方法管理。直接内存用于NIO,提高读写性能,手动回收。
|
13天前
|
存储 监控 算法
【JVM】如何定位、解决内存泄漏和溢出
【JVM】如何定位、解决内存泄漏和溢出
30 0