个人做网站备案多少钱,w5500做服务器网站,广州增城发布,快速建站软件排名对于Java应用程序来说#xff0c;Java堆#xff08;Java Heap#xff09;是虚拟机所管理的内存中最大的一块。Java堆是被所 有线程共享的一块内存区域#xff0c;在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例#xff0c;Java 世界里“几乎”所有的对象实例都…对于Java应用程序来说Java堆Java Heap是虚拟机所管理的内存中最大的一块。Java堆是被所 有线程共享的一块内存区域在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例Java 世界里“几乎”所有的对象实例都在这里分配内存。在《Java虚拟机规范》中对Java堆的描述是“所有 的对象实例以及数组都应当在堆上分配[1]”而这里笔者写的“几乎”是指从实现角度来看随着Java语 言的发展现在已经能看到些许迹象表明日后可能出现值类型的支持即使只考虑现在由于即时编 译技术的进步尤其是逃逸分析技术的日渐强大栈上分配、标量替换[2]优化手段已经导致一些微妙 的变化悄然发生所以说Java对象实例都分配在堆上也渐渐变得不是那么绝对了。 Java堆是垃圾收集器管理的内存区域因此一些资料中它也被称作“GC堆”Garbage Collected Heap幸好国内没翻译成“垃圾堆”。从回收内存的角度看由于现代垃圾收集器大部分都是基于分 代收集理论设计的所以Java堆中经常会出现“新生代”“老年代”“永久代”“Eden空间”“From Survivor空 间”“To Survivor空间”等名词这些概念在本书后续章节中还会反复登场亮相在这里笔者想先说明的 是这些区域划分仅仅是一部分垃圾收集器的共同特性或者说设计风格而已而非某个Java虚拟机具体 实现的固有内存布局更不是《Java虚拟机规范》里对Java堆的进一步细致划分。不少资料上经常写着 类似于“Java虚拟机的堆内存分为新生代、老年代、永久代、Eden、Survivor……”这样的内容。在十年 之前以G1收集器的出现为分界作为业界绝对主流的HotSpot虚拟机它内部的垃圾收集器全部 都基于“经典分代”[3]来设计需要新生代、老年代收集器搭配才能工作在这种背景下上述说法还 算是不会产生太大歧义。但是到了今天垃圾收集器技术与十年前已不可同日而语HotSpot里面也出 现了不采用分代设计的新垃圾收集器再按照上面的提法就有很多需要商榷的地方了。 如果从分配内存的角度看所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区 Thread Local Allocation BufferTLAB以提升对象分配时的效率。不过无论从什么角度无论如 何划分都不会改变Java堆中存储内容的共性无论是哪个区域存储的都只能是对象的实例将Java 堆细分的目的只是为了更好地回收内存或者更快地分配内存。在本章中我们仅仅针对内存区域的 作用进行讨论Java堆中的上述各个区域的分配、回收等细节将会是下一章的主题。 根据《Java虚拟机规范》的规定Java堆可以处于物理上不连续的内存空间中但在逻辑上它应该 被视为连续的这点就像我们用磁盘空间去存储文件一样并不要求每个文件都连续存放。但对于大 对象典型的如数组对象多数虚拟机实现出于实现简单、存储高效的考虑很可能会要求连续的 内存空间。 Java堆既可以被实现成固定大小的也可以是可扩展的不过当前主流的Java虚拟机都是按照可扩 展来实现的通过参数-Xmx和-Xms设定。如果在Java堆中没有内存完成实例分配并且堆也无法再 扩展时Java虚拟机将会抛出OutOfMemoryError异常。 [1] 《Java虚拟机规范》中的原文The heap is the runtime data area from which memory for all class instances and arrays is allocated。 [2] 逃逸分析与标量替换的相关内容请参见第11章的相关内容。 [3] 指新生代其中又包含一个Eden和两个Survivor、老年代这种划分源自UC Berkeley在20世纪80 年代中期开发的Berkeley Smalltalk。历史上有多款虚拟机采用了这种设计包括HotSpot和它的前身Self 和Strongtalk虚拟机见第1章原始论文是https://dl.acm.org/citation.cfm?id808261。