Java 杂谈JVM · Java虚拟机原理 · JVM上语言·框架· 生态系统

深入理解java虚拟机(一)java内存区域与内存溢出异常

2018-07-25  本文已影响2人  z七夜

写在前面:为了更加深入的了解java虚拟机,就看了一下《深入理解java虚拟机》这本书,一方面为了总结一下自己的认识,另一方面就是想与各位分享,如果有什么不对的地方,欢迎指正

在进行java开发的时候,开发人员一般都不需要关注内存的请求,释放等过程,那么jvm是怎样帮我们完成的呢
深入理解java虚拟机(二)垃圾收集器与内存分配策略

java内存区域与内存溢出异常

1、运行时数据区

栈中的异常
当线程请求栈深度大于虚拟机所允许的深度的时候,会抛出stackOverflowError异常,虚拟机栈可以动态扩展,如果在扩展的时候无法申请到足够的内存,就会抛出outofmemoryError异常

2、hotspot虚拟机对象探秘

1、对象的创建

当在new一个对象的时候,首先会去常量池(存放类的信息,属于方法区)定位这个类的信息,查看是否有加载这个类,如果没有这个类,先执行类加载,类加载完成之后,给这个对象在堆中分配内存,对象的内存大小在类加载完成之后就会确定,假如这个堆中的内存是整齐的,占用的在一边,空闲的在一边,中间放着一个指针作为分界点的指示器,分配内存就是将指针向空闲区域移动对象内存大小,这种分配叫做指针碰撞,假如堆中的内存不是整齐的,那么虚拟机就会维护一个列表,用于记录内存的使用情况,在分配内存的时候,会在列表中寻找一个足够大的内存分配给这个对象,这种方式叫做空闲列表,使用哪种分配方式由java虚拟机堆是否规整决定,是否规整由采用的垃圾采集器决定,使用serial,parnew等带有compact过程的收集器时候,系统采用的分配算法是指针碰撞,使用cms这种基于mark-sweep算法的收集器的时候,采用空闲列表,

new对象是很频繁的事,在并发下不是安全的,再给a分配内存的时候,指针还未修改,对象b使用l这个指针分配内存,解决方案:一种是对分配内存空间的动作进行同步处理,虚拟机采用CAS配上失败重试的方式保证更新操作的原子性,另一种是把内存分配的动作按照线程划分在不同的空间之中进行,

内存分配完成之后,虚拟机需要将分配到的内存空间都初始化为0,不包括对象头,虚拟机对对象进行必要的设置,例如这个对象是哪个类的实例,如何得到类的元数据信息,对象的哈希吗,对象的GC分代年龄信息等,这些信息放在对象的对象头中

2、对象的内存分配

对象在内存中存储,分为三个部分,对象头,实例数据,对齐方式

3、对象的访问定位

如何访问到堆中的实例呢,在栈中存放着实例的引用reference,有两种方式,一种是句柄,一种是指针引用

3、实战OutOfMemoryError

1、堆内存溢出

Heap

当我们指定了一定大小的堆内存,并一直new 对象,就会发生堆内存溢出的错误,因为对象不能被回收,内存不够

2、Stack Overflow

Stack Overflow

当我们不停的递归调用方法,造成栈的深度不够,即会发生此错误

更多内容请看后续,
QQ交流群:552113611

上一篇下一篇

猜你喜欢

热点阅读