JVM学习笔记-堆(Heap)
对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配①,但是随着JIT编译器的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换②优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也渐渐变得不是那么“绝对”了。
Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC堆”(Garbage Collected Heap,幸好国内没翻译成“垃圾堆”)。如果从内存回收的角度看,由于现在收集器基本都是采用的分代收集算法,所以Java堆中还可以细分为:新生代和老年代;再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。如果从内存分配的角度看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。不过,无论如何划分,都与存放内容无关,无论哪个区域,存储的都仍然是对象实例,进一步划分的目的是为了更好地回收内存,或者更快地分配内存。在本章中,我们仅仅针对内存区域的作用进行讨论,Java堆中的上述各个区域的分配和回收等细节将会是下一章的主题。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
以上描述截取自:
《深入理解Java虚拟机:JVM高级特性与最佳实践》 作者: 周志明
----------------------------------------------------------------------------------------------------------------------------------
Whenever a class instance or array is created in a running Java application, the memory for the new object is allocated from a single heap. As there is only one heap inside a Java Virtual Machine instance, all threads share it. Because a Java application runs inside its "own" exclusive Java Virtual Machine instance, there is a separate heap for every individual running application. There is no way two different Java applications could trample on each otherís heap data. Two different threads of the same application, however, could trample on each otherís heap data. This is why you must be concerned about proper synchronization of multi-threaded access to objects (heap data) in your Java programs.
The Java Virtual Machine has an instruction that allocates memory on the heap for a new object, but has no instruction for freeing that memory. Just as you canít explicitly free an object in Java source code, you canít explicitly free an object in Java bytecodes. The virtual machine itself is responsible for deciding whether and when to free memory occupied by objects that are no longer referenced by the running application. Usually, a Java Virtual Machine implementation uses a garbage collector to manage the heap.
java 程序在运行时创建的 所有类实例或数组都放在同一个堆中 。而 一个Java 虚拟机实例 只存在一个堆内存空间 ,因此所有的线程均 共享这个堆 。又由于一个java 程序独占一个Java 虚拟机实例,因而每个java 程序都有他自己的堆内存---- 他们之间不会相互影响。但是同 一个Java 程序的多线程却共享着同一个堆空间 ,在这种情况下,就得考虑多线程访问对象(堆数据)的同步问题了。
Java虚拟机有一条在堆中分配新对象的指令,但是没有释放内存的指令。java虚拟机的垃圾回收机制负责回收没有被使用的内存。
只要有一个对象引用,虚拟机就必须能够快速定位对象类型的数据。另外它也必须通过该对象引用访问相应的类数据(存储于方法区中的类型信息)。因此在对象中通常会有一个指向方法区的指针。
以上描述截取自:
《Inside the Java Virtual Machine 2nd Edition》 作者:Bill Venners