Java内存区域与内存溢出异常JVM运行时数据区
Java使用的内存大致被划分为5个部分
程序计数器参考计算机组成原理,程序计数器跟线程是绑定的,因此是线程私有的。虚拟机栈参考计算机组成原理,是运行Java方法时使用的栈,每个静态或非静态方法执行时会创建一个栈帧用于存储方法信息、局部变量(包括基本类型和对象引用,至于引用指向的对象则保存在堆中)等,线程私有。很明显,如果递归层次过深会导致StackOverflowError。本地方法栈运行Native方法时使用的栈,线程私有。方法区也就是Perm Generation,永久代。用于存放已被加载的类信息、每个对象保存的类型数据、常量(Java7开始已不包括字符串常量池)、静态变量等,JVM加载类后将Class文件中定义的常量保存在这里。由于存放的信息基本是常量性质的,因此是非线程私有的。堆保存对象实例,非线程私有。如果持有对象过多内存不足会导致OutOfMemoryError。
对象的定位通过句柄部分虚拟机实现中,非常量或静态变量的引用(也就是方法栈帧中保存的局部变量)指向的是句柄池中的指针,而句柄池中的指针指向的是真正的对象实例数据(堆中)或对象类型数据(方法区中)。这种方式的好处是引用直接指向的句柄池地址是不变的,而在句柄池中的指针由于GC的移动或复制等可能经常变化。
句柄访问
通过直接指针引用直接指向目标对象的对象实例数据(堆中)或对象类型数据(方法区中),在对象访问非常频繁的情况下减少一次寻址开销。HotSpot使用到的是直接指针定位。
......
共8张