JVM-Java内存区域与内存溢出异常
Posted 小马000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM-Java内存区域与内存溢出异常相关的知识,希望对你有一定的参考价值。
第二章:Java内存区域与内存溢出异常
2.1 运行时数据区
1:程序计数器 : 线程私有,较小的内存空间,当前线程所执行的字节码的行号指示器,唯一不会发生错误的内存区域
2:虚拟机栈: 线程私有,生命周期和线程相同,为虚拟机执行Java方法服务,指的是Java内存模型,可发生StackOverflowError(栈溢出错误)和OutOFMemoryError============待后续详细学习(其中每一个栈帧中分配的内存大小基本上在类结构确定下来就是已知的)
3:本地方法栈:线程私有,为虚拟机使用到的native方法服务,可发生StackOverflowError(栈溢出错误)和OutOFMemoryError
4:Java堆:线程共享,最大的内存空间,GC的主要区域,可发生OutOFMemoryError
5:方法区:线程共享,存储被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据,GC的主要目的是对常量池的回收和类型的卸载,可发生OutOFMemoryError
jdk1.7:永久代 jdk1.8:metaspace
6:运行时常量池:方法区的一部分,Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有常量池信息,用于存放编译期各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池,可发生OutOFMemoryError
7:直接内存:并不是虚拟机运行时数据区的一部分,直接内存的分配会受到本机器总内存的大小限制,可发生OutOFMemoryError,不会主动使虚拟机发生垃圾回收,只能在虚拟机发生回收时顺便回收内存。
2.2 HotSpot虚拟机对象
1:对象的内存布局
运行时数据:存储对象自身的运行时数据,包括哈希吗(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等,官方称为Mark Word,非固定的数据结构
类型指针:指向它类元数据信息的指针,并不是所有的虚拟机实现都在对象数据上保留类型指针 注意:Java数组的对象头中还有一块用于记录数组长度的区域
实例数据:包括类自己、父类继承的、子类中定义的信息,将父类、类、子类的信息整合,相同宽度的字段被分配到一起
对齐填充:不是必然存在的,也没有特别的含义,仅仅起着占位符的作用
2:对象的访问定位
注:对象移动和访问在Java中是非常频繁的,HotSpot虚拟机使用的是直接指针访问对象的方式,但两种方式都很常见
通过句柄访问对象:优势是reference中存储的是稳定的句柄地址,对象发生移动时只会改变句柄中的实例数据指针,reference本身不需要改变
通过直接指针访问对象:优势是速度快,节省了一次指针定位的时间开销
3:VM参数配置
Java堆参数设置:-Xms20m -xmx20m -xX:+HeapDumpOnOutOfMemoryError(虚拟机出现内存异常时Dump 出当前的内存堆转储快照以便后续分析 heap space)
Java栈参数设置:-Xss128k 栈内存大小 = 所有线程占有内存大小,每个线程占有内存大小 = 线程执行过程中每个方法(栈帧)的大小之和
方法区和运行时常量池:-XX:permSize=10M -XX:MaxPermSize=10M (PermGen space)
直接内存:-XX:MaxDirectMemorySize=10M,如果不指定则默认和Java堆最大值一样
ps:欢迎大家评论,批评指正
以上是关于JVM-Java内存区域与内存溢出异常的主要内容,如果未能解决你的问题,请参考以下文章