JVM虚拟机-自动内存管理机制

一.虚拟机的运行时数据区

包括:方法区,堆,栈(本地方法栈,虚拟机栈),程序计数器

1.程序计数器(线程私有):

可以当作一个行号指示器,通过数字改变来选取下一条需要执行的指令,分支,循环,跳转,异常等都是依赖计数器来完成的。

虚拟机的多线程是通过线程轮流切换来实现,所以在某一个确定的时刻只能执行一个线程中的一条指令,这就要求程序计数器是线程私有的来保证互不干扰,并且切换以后知道下一条要执行什么指令。

2.虚拟机栈(线程私有):

线程私有,生命周期与线程相同。
每个方法执行的时候回创建一个栈帧,来存储局部变量表,操作数栈,动态链接,方法出口。
局部变量表存储各种基本数据类型和引用数据类型的地址。

3.本地方法栈(线程私有):

与虚拟机栈的区别在于,虚拟机栈为虚拟机执行java方法,本地方法栈为虚拟机使用到的native方法服务。有的虚拟机会将二者合二为一。

3.堆(线程共享):

存放对象实例。
可以存在物理上不连续的内存空间。如果堆中没有内存完成实例分配并且堆无法扩展,就会产生OutOfMemoryError。

4.方法区(线程共享):

存放类信息,常量,静态变量,即时编译器编译后的代码等。
可以存在物理上不连续的内存空间。如果堆中没有内存完成实例分配并且堆无法扩展,就会产生OutOfMemoryError。

5.运行时常量池:
6.直接内存:

直接内存不是jvm数据区的一部分,但是这部分内存会被频繁调用。
在NIO中,阴图一种基于通道和缓冲区的io方式,可以使用native函数库直接分配堆外内存,因此在配置虚拟机参数的时候,如果忽略直接内存也有可能导致OutOfMemoryError。

二.虚拟机的使用方法

1.对象的创建:

代码层面中的new一个对象,一般在jvm中会有以下几个操作:
首先检查这个指令的参数是否能在常量池中找到这个类的符号引用。。。。
然后分配内存,分配内存有两种方法,如果堆在内存中绝对规整,可以通过指针碰撞(Bump the Pointer)的方法,就是将指针挪动和对象大小相等的一段距离;第二种是通过空闲列表(Free List),维护一个记录记录内存块的列表,来分配实例。
但是为了保证并发安全,可能需要同步,或者采用cas方法进行失败重试,或者直接采用本地线程分配缓冲(Thread Local Allocate Buffer)。即给每个线程直接预先分配号一段内存空间,只有内存空间不足的时候才需要同步锁定来分配新的TLAB。

2.对象的内存布局:

对象头,实例数据,对象填充。
对象头一部分包含哈希码,GC分代年龄,锁状态,偏向线程ID等等。另一部分是类型指针,指向它的类元数据的指针。
实例数据是有效存储信息。
对象填充是占位符,自动内存管理可能需要对象地址必须是8字节的整数倍,所以需要对象填充补全。

3.对象的访问定位

定位一个堆上的具体对象需要通过栈上的reference数据。定位的方法取决于虚拟机的实现,目前主流的访问方式有使用句柄直接指针两种方式。
句柄中包含对象实例数据和类型数据各自的具体地址信息的指针。
直接指针里则直接存放对象实例数据地址和类型数据的指针。

三.OutOfMemoryError

1.堆溢出

OutOfMemoryError:Java heap space
当对象数量过多的时候,可能会产生这种情况,在这种情况下,重点确认内存中的对象是否必要,也就是分清楚到底是内存泄漏还是内存溢出,如果是发现有导致垃圾收集器无法收集的时候,就是内存泄漏,修改代码即可,如果不存在泄漏也就是对象都是必须的,那就考虑修改虚拟机的堆参数(-Xmx,-Xms),增大堆内存,或者是查看是否有某些对象生命周期过长或者持有状态时间过长,尝试减少内存消耗。

2.虚拟机栈和本地方法栈溢出

栈容量一般通过-Xss设定
在单个线程下,如果栈帧过大或者虚拟机栈容量太小,都容易出现stackoverflowerror。
但是还有另一种情况,如果不限于单线程,通过不断建立线程的方式会产生内存溢出异常。在这种情况下,为每个线程的栈空间分配的越大越容易异常,因为操作系统分配给每个进程的内存是由限制的,比如32位虚拟机限制为2GB,减去最大堆容量和最大方法区容量以后剩下的就是栈容量,如果每个栈空间越大,可建立的栈数量就越小,就越容易出现outofmemory,因此如果线程数过多产生内存溢出的时候,在无法减少线程数的情况下,可以考虑减少最大堆和栈容量的方式来换取过呢更多的线程。

3.方法区和常量池溢出

permGen space
https://blog.csdn.net/jwandbj/article/details/77874031
-XX:permSize来限制常量池容量。
经常大量产生class的类中要特别注意回收状况。

4.本机直接内存溢出

-XX:MaxDirectMemorySize指定,如果不指定,则默认与java堆的最大值一样,直接内存溢出异常没有特殊的标记,所以当发现dump文件很小,又引用了NIO的时候可以考虑是否是直接内存溢出了。

OOM的几种情况及解决方案:

https://zhuanlan.zhihu.com/p/79355050

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容