【JVM】Java内存模型

JVM基本结构

这里写图片描述

简介:PC寄存器:
1、指向下一条指令的地址
2、每个线程都拥有一个PC寄存器
3、在线程创建时创建
4、执行本地方法时,pc的值为undefined
执行引擎:用来操作数据和发布指令

内存区间

主要包括方法区,Java堆,Java栈和本地方法栈四部分。

方法区

通常方法区会和永久代联系在一起,他们在逻辑上是与Java堆分开的。在方法区中主要用来

保存类的加载信息
类型的常量池
字段和方法信息
方法字节码

在方法区也会发生内存泄漏。它保存了Java类定义,但是,它们是可以变成“无用”的。以一个部署到应用程序服务器的Java web程序来说,当该应用程序被卸载的时候,你的EAR/WAR包中的所有类都将变得无用。只要应用程序服务器还活着,JVM将继续运行,但是一大堆的类定义将不再使用,理应将它们从永久代(PermGen)中移除。如果不移除的话,我们在永久代(PermGen)区域就会有内存泄漏。当永久代发生内存泄漏时,GC会直接执行full GC。
常量池
常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于类,方法,接口等中的常量,也包括字符串常量。

Java堆

1、应用对象都保存在Java堆中,Java堆可以根据对象的大小的变化而变化。所以一般都是在运行时分配内存。
2、所有线程共享Java堆
3、采用GC分代的垃圾回收机制
4、Java堆是GC工作的主要空间
在Java堆中根据GC垃圾回收机制的复制算法,可以分为三部分分别是新生代,幸存代和老年代。其中图中s0和s1是幸存代。s0和s1是大小一样的两个内存区域。
这里写图片描述
其中jvm在分配内存时,会把新创建的对象分配到新生代,个别占用内存较大的对象会放在老年代。
经过一次GC回收后,仍然存活的对象会进入幸存代。
而s0和s1中的对象经过多次GC回收后仍然存活的对象则进行老年代。
关于复制算法,下篇博客会做详细介绍

Java栈

1、Java栈是每个线程都会拥有一个自己私有的Java栈空间
2、栈由一系列帧组成,因此Java栈也叫作帧栈
3、帧保存一个方法的局部变量,操作数栈,常量池指针(对象的引用)
4、每一次方法调用创建一个帧,并压栈
操作数栈
Java中没有寄存器,所有参数的传递都是使用操作数栈来进行的。既然是栈就遵循先进后出的原则。
和局部变量区一样,操作数栈也是被组织成一个以字长为单位的数组。但是和前者不同的是,它不是通过索引来访问,而是通过标准的栈操作—压栈和出栈—来访问的。比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用

栈上分配


我们在编写程序时,程序为对象分配的了空间,但是却没有删除,这样长久下去会造成内存泄漏的问题(堆空间不足)。
所以,我们在创建变量时应尽量声明为局部变量且先不要实现实例化(new),在用的时候在实例化,这样的内存分配称为栈上分配。

栈上分配的优点:
1、小对象在没有逃逸的情况下,可以直接分配在栈上
2、直接分配在栈上,可以自动回收,减轻GC压力

注意:大对象或者逃逸对象无法栈上分配
逃逸对象:在一个线程上使用的对象,在其他线程上也要使用,这个时候需要被多个线程共享,那么必须分配到堆空间中。

栈上分配容易出现的异常:java.lang.StackOverflowError
原因分析:
根本原因是这样的,对于每一个线程,都有一个java栈 ,当有一个方法被调用的时候,会产生一些跟这个方法相关的信息,如方法名,参数,中间变量等等,这些叫做栈帧 ,当一个方法执行完毕 这个栈帧才会从栈顶pop掉 你递归的话 会一直向栈里push栈帧 而这个java栈是有一定的长度或深度的,当栈满了,无法再进行push的时候 就出现你上面的异常了。所以尽量不要使用递归调用。

通常来讲,一般栈区远远小于堆区的,因为函数调用过程往往不会多于上千层,而即便每个函数调用需要1K的空间(这个大约相当于在一个C函数内声明了256个int类型的变量),那么栈区也不过是需要1MB的空间。通常栈的大小是1-2MB的。通常递归也不要递归的层次过多,很容易溢出.

内存模型

这里写图片描述
每一个线程都有一个工作内存和主存独立,工作内存存放主存中变量的值的拷贝

当数据从主存复制到工作存储时,必须出现两个动作:

1、由主存执行的读(read)操作
2、由工作内存执行的相应的load操作

当数据从工作内存拷贝到主内存时,也出现两个操作:

1、由工作内存执行的存储(store)操作
2、由主内存执行的相应的写(write)操作

各个线程内的操作都是有序的,但是在线程外观察,操作是无序的。这就涉及到了指令重排。指令重排会破坏代码执行的有序性,通常我们采用加锁来实现同步功能。
以上就是是关于Java内存模型中一些相关知识。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值