深入理解Java虚拟机(二)

jvm内存结构通用模型(此图为java6)
在这里插入图片描述

1.程序计数器

在这里插入图片描述
注意点:
1.此处没有内存溢出异常(可以这样理解,因为我们操作不了程序计数器,而是由jvm调用,所以会很严谨,不会出现内存溢出的异常)

2.java虚拟机栈

在这里插入图片描述

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

在这里插入图片描述
注意点:
1.二者结构模型很类似,所以本地方法栈和虚拟机栈在hotSpot中融为一体了

4.Java堆

在这里插入图片描述
堆主要存放Java在运行过程中new出来的对象,凡是通过new生成的对象都存放在堆中,对于堆中的对象生命周期的管理由Java虚拟机的垃圾回收机制GC进行回收和统一管理。类的非静态成员变量也放在堆区,其中基本数据类型是直接保存值,而复杂类型是保存指向对象的引用,非静态成员变量在类的实例化时开辟空间并且初始化。

5.方法区

方法区:是各个线程共享的内存区域,它用于存储class二进制文件,包含了虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。它有个名字叫做Non-Heap(非堆),目的是与Java堆区分开。
1.永久代是hotSpot虚拟机在java7中对方法区的实现,虽然逻辑上像是单独一部分区域,重新起来一个名字叫做非堆,但物理上是堆内存一部分。为的是方法区也可以用堆内存的GC垃圾回收器,而不用重新针对方法区做GC操作。

  1. List item

2.元空间是hotSpot虚拟机在java8中对方法区的实现,物理上以及不属于堆内存,而是属于系统物理内存,所以1.8元空间不存在OOM内存溢出的情况。
3.无论是元空间还是永久代,都不等同与方法区,只是方法区的一种实现,在其他虚拟机中并没有此概念。
4.关于常量池:
jdk 1.7之前常量池是存放在永久代(hotspot虚拟机对方发区的实现)中 ,方法区与堆是独立的,从这张内存图中也能看出来。
jdk 1.7常量池从永久代中移到了堆内存中,属于堆内存的一部分。
Java8移除了永久代并由元空间(metaspace)代替,存放在本地内存(native space)中。并没有对常量池再做变动。即常量池一直在堆中。

关于对象

1.对象的结构

在这里插入图片描述

2.对象的访问定位

Java是通过虚拟机栈中的局部变量表中的reference数据来操作Java堆上的具体对象。但reference只是虚拟机规范中规定指向一个对象的引用,它并没有定义这个引用通过何种方式去定位、访问堆中的对象的具体位置,所以对象访问方法也取决于虚拟机的实现而定的。目前主流的访问方式有使用句柄和直接指针两种。

一、句柄访问
如果使用句柄访问,Java堆中将会划分出一块儿内存作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据地址和对象类型数据地址。实际上是采用了句柄池这样一个中间介质进行了两次指针定位,有效的避免了对象的移动或改变直接导致reference本身发生改变。
在这里插入图片描述
二、直接指针访问
如果使用直接指针访问,那么Java堆对象的布局必须考虑如何放置访问类型的数据的相关信息,而reference中存储的直接就是对象地址,而不再是句柄地址信息,相当于在reference与对象地址信息直接少了句柄池这样一个中间地址,reference中直接存储的就是对象地址。

这种定位方式也就导致了在对象被移动时,reference本身必须发生改变。由于对象的访问在Java中非常的频繁,时间开销的减少也是一种可观的执行成本。例如,常见的HotSpot虚拟机就使用的是直接指针访问方式。
在这里插入图片描述

内存分配原则介绍

GC种类
**1.Young GC **:
又叫新生代GC,指发生发生在Eden、S0、S1区
因为Java对象大都朝生息死的原因,所以新生代的Eden区和S0 内存经常会满,所以Monitor GC会特别频繁
Monitor GC只会清理新生代的内存,所以Monitor GC一般很快

2.Monitor GC
发生在Eden区,伴随着每次younGC的触发而触发

3.Major GC:
部分人又叫Old GC、老年代GC,指发生在老年代的垃圾收集
由于老年代的对象不会新增的很频繁,所以Major GC不会太频繁
发生Full GC一般都会伴随着一次Major GC

4.Full GC:
整体GC,通常会触发发生123中GC

1、对象优先分配在Eden区
如果Eden区没有足够的空间时,虚拟机执行一次Minor GC。

2、大对象直接进入老年代
大对象是指需要大量连续内存空间的对象,大数组等。这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存拷贝(新生代采用复制算法收集内存,拷贝损耗性能)这里大对象大大小是可以指定的。

3、长期存活的对象进入老年代
虚拟机为每个对象定义了一个年龄计数器,如果对象经过了1次Minor GC那么对象会进入Survivor区,之后每经过一次Minor GC那么对象的年龄加1,达到阀值对象进入老年区。当然了4的情况也有可能在阀值前发生,从而提早进入老年代。

4、动态判断对象的年龄
如果Survivor区中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代。

5、空间分配担保
每次进行Minor GC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次Full GC,如果小于检查HandlePromotionFailure设置,如果true则只进行Monitor GC,如果false则进行Full GC。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值