jvm(四)

jvm

hotspot虚拟机

对象的创建
  • 虚拟机遇到new时,先去常量池定位符号引用,看这个符号所代表的类是否被加载、解析和初始化。若无,必须先执行类加载过程。
  • 加载完成之后,即为新生对象分配内存。分配方式有指针碰撞与空闲列表,选择哪种由垃圾收集器是否带有压缩整理功能决定。
  • 执行new之后,会执行init方法,将对象初始化。
对象的内存布局
  • 布局分三块区域:对象头、实例数据、对齐填充
  • 对象头包括两部分信息
    • 第一部分用于存储对象自身的运行时数据
    • 第二部分是类型指正,即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
对象的访问定位
  • Java通过栈上的reference数据来操作堆的具体对象。
  • 主流访问方式
    • 句柄,Java堆会划分出一块内存作为句柄池,reference中存储的就是对象的句柄地址,在对象被移动时只会改变句柄的实际数据指针,而reference本身不需要修改。
    • 直接指针访问方式,好处是速度快。

实战:outofmemoryerror异常

Java堆溢出
  • Java堆内存的oom异常是实际应用中常见的内存溢出异常情况。
  • 通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析。
    在这里插入图片描述
  • 当出现Java堆内存溢出时,异常堆栈信息“java.lang.OutOfMemoryError”会跟着进一步提示“Java heap space”。
  • 要解决这个区域的异常,一般的手段是先通过内存映像分析工具(如Eclipse Memory Analyzer)对dump出来的堆转储快照进行分析,确认内存中对象是否必要,分清楚是内存泄漏还是内存溢出。
  • 如果内存泄露,可进一步通过工具查看泄露对象到GC Roots的引用链。可以比较准确地定位出泄露代码的位置。
  • 如果不存在内存泄露(内存中对象必须都活着),检查虚拟机堆参数与机器物理内存对比看是否还可以调大,检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。
虚拟机栈和本地方法栈溢出
  • 对于Hotspot来说,栈容量只由-Xss参数设定。
  • 关于虚拟机栈和本地方法栈,在Java虚拟机规范中描述了两种异常(本质上只是对同一件事的两种描述):
    • 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出stackoverflowerror异常。
    • 如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出outofmemoryerror异常。
  • 在单个线程下,无论是由于栈帧太大还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是stackOverflowError异常。
  • 多线程情况下,每个线程分配的内存越大,越容易产生内存溢出异常。其原因主要在于操作系统分配给每个进程的内存是有限制的。(Windows 32位限制内存为2G)
方法区和运行时常量池溢出
  • 常量池分配在永久代中,可以通过-XX:PermSize和-XX:MaxPermSize限制方法区大小,从而间接限制其中常量池的容量。
    在这里插入图片描述
  • 运行时常量池溢出,在outofmemoryerror后面跟随的提示信息是“PermGen space”,说明运行时常量池属于方法区(Hotspot虚拟机中的永久代)的一部分。
  • 方法区用于存放class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。
  • jvm上的动态语言通常都会持续创建类来实现语言的动态性。
  • 方法区溢出也是一种常见内存溢出异常,在经常动态生成大量class的应用中,需特别注意类的回收状况。这类场景有:CGLib字节码增强、动态语言、大量jsp、或动态产生jsp文件的应用、基于 osgi的应用。
本机直接内存溢出
  • directmemory容量可以通过-XX:MaxDirectMemorySize指定,若不指定,则默认与Java堆最大值一样。
    在这里插入图片描述
  • 由directMemory导致的内存溢出,一个明显特征是在heap dump文件中不会看见明显的异常。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值