JVM学习笔记-内存划分

3 篇文章 0 订阅

一.jvm在程序执行中,会把内存划分为以下部分

--线程共享区

--1.java堆区

--2.方法区

--线程私有区(随着线程的消亡而消亡,不用过多考虑回收,编译时确认所需大小)

--3.虚拟机栈

--4.本地方法栈

--5.程序计数器

(其中抛出的各种异常如下:

OutOfMemoryError:java堆,方法区,多线程时候虚拟机栈和本地方法栈

StackOutFlowError:虚拟机栈,本地方法栈单线程运行时

**其中程序积水不会有内存溢出的异常)

1.java堆区

几乎所有的对象实例和数组都在这分配内存。Java Heap是垃圾收集器管理的主要区域,因此很多时候也被称为“GC堆”。根据Java虚拟机规范的规定,Java堆可以处在物理上不连续的内存空间中,只要逻辑上是连续的即可。如果在堆中没有内存可分配时,并且堆也无法扩展时,将会抛出OutOfMemoryError异常。

不能在栈上存储数组和对象。因为栈帧被设计为创建以后无法调整大小。栈帧只存储指向堆中对象或数组的引用。与局部变量数组(每个栈帧中的)中的原始类型和引用类型不同,对象总是存储在堆上以便在方法结束时不会被移除。对象只能由垃圾回收器移除。

2.方法区

用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区域又被称为“永久代”。它和Java Heap一样不需要连续的内存,可以选择固定大小或可扩展,另外,虚拟机规范允许该区域可以选择不实现垃圾回收。

3.虚拟机栈

生命周期和线程同步。用来描述java程序执行时候的内存模型,每一个方法调用时产生一个栈帧,栈顶的方法对于当前的执行引擎有效,称为当前栈帧。帧用于存储局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息。

在编译程序代码时,栈帧中需要多大的局部变量表、多深的操作数栈都已经完全确定了。 不受运行时候变量的影响。

!!栈帧中存放的数据结构:

<1>.局部变量表

在编译成.class文件时候就确认了所需的空间

<2>.操作数栈

操作数栈的最大深度同样在编译时就完全确定了。32位数据类型所占的栈容量为1,64为数据类型所占的栈容量为2。当一个方法开始执行时,它的操作栈是空的

<3>.动态连接

<4>.方法返回地址

4.本地方法栈

该区域与虚拟机栈所发挥的作用非常相似,只是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为使用到的本地操作系统(Native)方法服务。

5.程序计数器

jvm下一条执行指令的地址。若本地native方法,pc值为undefined。用来追踪指令的执行位置,其实是指向方法区内存的一个内存地址。

每条线程都有一个独立的的程序计数器,各线程间的计数器互不影响,因此该区域是线程私有的。

内存溢出情况:

java堆:不断new对象并保存引用,保证不被回收

方法区:创建大量动态类(方法区非常量池部分),或者大量调用String的intern()方法

虚拟机栈和本地方法栈:递归无出口(单前程),不断创建线程并且每个线程无线增加内存

例子:

Object obj = new Object();

方法区中借助类加载器加载了该类的静态变量到内存中,同时堆中创建java.lang.Class对象来封装数据结构,产生指针指向方法区数据。new操作在堆区生成了类的实例。在此次操作中,java虚拟机栈在栈帧中记录了obj的引用放入栈。

draw.io

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值