JVM--基础--03--内存区域--堆

JVM–基础–03–内存区域–堆


1、结构图

JVM--基础--03--内存区域--堆_第1张图片

2、堆

2.1、Java堆的特征

  1. 几乎所有的对象都存放在堆上。并且java堆是完全自动化管理的,通过垃圾回收机制,垃圾对象会被自动清理。
  2. 可能出现 OutOfMemoryError 异常。
  3. java堆最为常见结构是将整个java堆分为新生代和老年代。
    1. 新生代存放新生对象或者年龄不大的对象
    2. 老年代则存放老年对象。
    3. 新生代有可能分为eden区(8)、from区(1)、to区(1),from和to区是大小相同、可以互换角色的内存空间。
  4. 所有线程共享的,因此在其上进行对象内存的分配均需要进行加锁,这也导致了new对象的开销是比较大的
  5. Sun Hotspot JVM为了提升对象内存分配的效率,对于所创建的线程都会分配一块独立的空间TLAB(Thread Local Allocation Buffer),其大小由JVM根据运行的情况计算而得,在TLAB上分配对象时不需要加锁,因此JVM在给线程的对象分配内存时会尽量的在TLAB上分配,在这种情况下JVM中分配对象内存的性能和C基本是一样高效的,但如果对象过大的话则仍然是直接使用堆空间分配
    1. TLAB仅作用于新生代的Eden Space,因此在编写Java程序时,通常多个小的对象比大的对象分配起来更加高效。
  6. 所有新创建的对象都将会存储在新生代中。如果新生代的数据在一次或多次GC后存活下来,那么将被转移到老年代。
  7. 新创建的对象总在Eden Space。

2.2、堆空间的一般结构

JVM--基础--03--内存区域--堆_第2张图片

  1. 在绝大多数情况下,对象首先分配在eden区,在一次新生代回收之后,如果对象还存活,则进入from或者to,每经过一次新生代回收,对象如果存活,它的年龄就会加1。当对象的年龄达到一定条件(默认年龄15)后,就会被认为是老年对象,从而进入老年代。
  2. 默认比例:年轻代:老年代=1:2

2.3、栈到堆的关联过程

JVM--基础--03--内存区域--堆_第3张图片

2.4、案例

JVM--基础--03--内存区域--堆_第4张图片

SimpleHeap实例本身分配在堆中,描述SimpleHeap类的信息存放在方法区,main函数中的s1 s2局部变量存放在java栈上,并指向堆中两个实例。

2.5、堆溢出代码案例

public class TestHeap {
	// 分配128Kb的内存给数组,方便堆内存溢出
	byte[] bis = new byte[128 * 1024];
 
	public static void main(String[] args) {
		List list = new ArrayList<>();
		//增加堆内存
		while (true) {
			list.add(new TestHeap());
		}
	}
}
结果:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.fei.zhou.day1.TestHeap.(TestHeap.java:8)
at com.fei.zhou.day1.TestHeap.main(TestHeap.java:14)

2.6、总结:

  1. 堆中存的是对象。
    1. 对象的大小是不可估计的,或者说是可以动态变化的
  2. 栈中存的是基本数据类型和堆中对象的引用。
    1. 一个对象引用大小是4btye。

你可能感兴趣的:(JVM,java,开发语言)