JAVA内存模型

本文详细介绍了Java内存模型,包括线程私有的程序计数器和虚拟机栈,以及线程共享的堆和方法区。讨论了栈帧、本地方法栈、新生区、养老区和永久区的概念,以及不同JDK版本中方法区的变化。还提到了常见的内存溢出异常以及如何设置堆空间大小,并强调了垃圾回收在堆内存管理中的作用。
摘要由CSDN通过智能技术生成

目录

1、Java内存模型图

2、程序计数器

3、虚拟机栈

4、本地方法栈

5、堆空间

6、方法区

7、方法区在不同 JDK 版本的变化

 


在Java中对象的创建与销毁都是取决于它的存储位置的,所以在这里详谈一下Java的内存模型,及其包含的内容。

1、Java内存模型图

img

绿色区域是线程共享的部分

红色部分是线程私有的部分

2、程序计数器

程序计数器是Java内存中分配的一小块内存,用来存放执行某些线程指令,由字节码解释器的工作时通过改变计数器的值来选择下一条要执行的字节码执行。属于线程的私有内存。因为Java是轮流执行线程也就是说同一时刻,一个处理器只能执行一个线程的指令。这是唯一一个在任何情况下都不会抛出OutofMemoryError错误的一块内存。他的生命周期随着线程的创建而创建,随着线程的结束而消亡。

作用:

1、字节码解释器通过改变程序计数器来依次读取指定,从而实现代码的流程控制,如,顺序执行,跳转等

2、在多线程下,程序计数器用于记录当前线程的执行位置,从而当线程切换的时候能知道线程上次执行在那

3、虚拟机栈

虚拟机栈也是线程私有的内存,主要是描述Java方法的执行的内存模型,每个方法被执行的时候都回去同时创建一个栈帧,用于存放局部变量表,操作数栈,动态链接等,每一个方法被调用直至执行完成的过程,对应一个栈帧在虚拟机栈中从入栈到出栈过程。

img

在Java中java代码的执行过程实际上就是方法之间的相互调用。在图中每一个栈帧中存储局部变量表、操作数栈、动态链接、方法出口信息。

局部变量表中存放八大原始类型,对象引用(可能是指向对象的起始地址的引用指针,也可能是一个代表对象的句柄或者其他与他相关的位置信息),局部变量表所需要的内存在编译阶段完成分配,在方法的执行期间不会改变局部变量表的大小

img

                                                        虚拟机栈详细图解

Java虚拟机栈会出现两种异常StackOverFlowError和OutOfMemoryError

1、StackOverFlowError:若java虚拟机栈的内存大小不允许动态扩展,当线程请求的栈的深度超过当前虚拟机栈最大的深度的时候就会抛出StackOverFlowErrorStackOverFlowError

2、OutOfMemoryError:若java虚拟机栈的内存大小允许动态扩展,且当线程请求栈是内存用完了,无法进行动态扩展,此时抛出OutOfMemoryError异常。

我们也可以自己设置虚拟机的内存大小,可通过下面的参数在JVM中设置虚拟机栈的大小设置:

-Xss:用于设置栈的大下,栈的大小决定了方法的调用深度,也就是最多调用的方法个数

-Xss10m:表示为虚拟机开辟了大小为10m大小的空间

注意:Java虚拟机栈是线程私有的。

        生命周期随着线程创建而创建,随着线程的消亡而死亡。

4、本地方法栈

顾名思义就是用来存放本地native方法的内存和虚拟机栈的作用是非常类似的。

区别:虚拟机栈是为虚拟机提供Java方法(字节码)的服务,而本地方法栈则为虚拟机栈使用到的native方法服务,这块内春也会出现两种异常StackOverFlowError和OutOfMemoryError,同时也是线程私有的空间,其生命周期随着线程创建而创建,随着线程的消亡而死亡。

5、堆空间

堆在启动虚拟机的时候就会创建堆内存,该内存是所有线程共享的一块内存空间。主要是用来存放对象的实例。该内存是主要的回收垃圾的地方。

堆中分为三部分:

新生区:创建对象实例都是存储在这一块,也就是通过new出来的对象

养老去:通过重量级的垃圾回收后新生区内存满后,进行存储数据,其数据不可能在被改变

永久区:存储的是JDK自带的一些jar包,interface元接口,以及一些类信息。在这一块内存中不存在垃圾回收,关闭jvm后内存里面的东西就会被释放。

造成在永久区就出现了OOM的原因:加载一个类的时候加载了太多的jar包,部署了Tomcat了很多的应用。

处理OOM问题:使用jprofiler工具进行快速查找出现问题的代码。

好处:会生成一个Dump文件,获取大的对象,获取堆中的数据

我们也可以自己设置对空间的大小,可通过一下参数进行相应的设置:  -Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

-Xms128m JVM初始分配的堆内存 -Xmx512m JVM最大允许分配的堆内存,按需分配 -XX:PermSize=64M JVM初始分配的非堆内存 -XX:MaxPermSize=128M JVM最大允许分配的非堆内存,按需分配

6、方法区

该区域也是线程共享的,主要是用来存放静态变量、final修饰的变量、加载过的类信息、即编译器编译过后的代码等内容。在该内存中存在垃圾回收很少,即使有都是对常量池的回收和变量类型的卸载,方法区和堆空间一样,是线程共享的区域,作用是存放类的信息,静态变量等

在一定的条件下会被GC操作,方方法区使用的内存超过其允许的大小时,会抛出OutOfMemoryError的异常

HotSpot虚拟机中方法区也称之为“永久代”,设计时用永久代来实现方法

方法区和永久代

img

7、方法区在不同 JDK 版本的变化

img

运行时常量池:String s="hello"

常量池:用于存放编译期生成的各种字面量和符号引用

通过上图可知,在JDK1.6及之前存放在方法区,在JDK1.7之后放在老年代

方法区和元空间的区别:

img

以上就是对Java内存模型及其相应的说明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值