Thinking in java-3 Java 堆和栈

来源:互联网 发布:php 检验 excel 编辑:程序博客网 时间:2024/05/29 09:12

1. Java Heap Space

  • Java heap空间是java运行时分配内存给对象(OBJECTS)和JRE类的。所有的对象都被创建在堆内存空间上。
  • GC 作用于堆内存上释放未被引用的对象的内存。
  • 堆内存空间创建的对象能被全局访问,可以在应用的任何地方被引用。

2. Java Stack Memory

  • Java栈空间用于线程的执行。
  • Stack memory包括短期存活的特定方法值以及方法中对于堆中其他对象的引用。
  • 栈内存引用顺序是LIFO(Last in First out)顺序。
  • 每当方法被调用时,一个新的内存块在该栈上被创建--用来存放局部基本数据类型值和方法中对于其他对象的引用。
  • 方法结束时,方法所在代码块不可用(包括局部基本类型和引用)。
  • 栈内存空间相较于堆空间所占内存更小。4. 堆和栈内存在Java 内存模型中的异同

3. 堆栈实例


package com.fqyuan.thinking;public class TestMemory {public static void main(String[] args) { // Line 1int i = 1; // Line 2Object obj = new Object(); // Line 3TestMemory mem = new TestMemory(); // Line 4mem.foo(obj); // Line 5} // Line 9private void foo(Object param) { // Line 6String str = param.toString(); // Line 7System.out.println(str);} // Line 8}

  • 当我们一开始运行程序,所有的运行时类被装载在堆空间。在运行到line1的main()方法时,Java Runtime 创建了用于main()方法线程使用的栈内存。
  • 在运行到line2时,我们创建了一个基本类型局部变量,所以它被创建并被存储在main()方法的栈内存区域。
  • 在运行到line3时,我们创建了一个Object, 该对象的实例被创建在堆内存,在栈内存中包含该实例对象的引用。对于line4亦然,不再赘述。
  • 在运行到line5时,我们调用了foo()方法,在当前栈的栈顶将开辟一片内存给foo()方法使用。因为java函数是Pass by value 方式的,所以运行到line6时会有一个新的指向Object对象的引用在foo()的栈空间被创建。
  • 运行到line7时,在String Pool中存放着String对象实例,并在foo()的stack空间有其引用。
  • 运行到line8时,foo()方法终止,此时栈中分配给foo()的内存块被释放。
  • 运行到9时,main()方法终止,分配给main()方法的栈内存被销毁。同时程序也在这一行终止,因而Java Runtime 释放所有的内存,并终止该程序的执行。

4. 堆和栈内存在Java 内存模型中的异同

  1. 堆内存是被application的所有部分所共用的,而栈内存只被一个执行的线程所使用。
  2. 不管对象何时被创建,对象实例总是存放在堆内存,而在栈内存存放的是该对象的引用。栈内存中存放的只是基本类型局部变量和堆空间中对象的引用。
  3. 堆空间中的对象是全局可访问的,而栈内存的数据不能被其他线程访问。
  4. 栈空间的内存管理是通过LIFO方式完成的,而堆空间的内存管理比其更复杂,因为堆空间的变量是全局可用的。
  5. 栈空间生命周期是短时存在的,而堆内存生命周期是从开始一直到应用执行的结束。
  6. 我们可以用-Xms和-Xmx JVM选项来定义堆内存的默认大小和最大值。我们可以用-Xss来定义栈内存空间的大小。
  7. 当栈内存满时,Java runtime 抛出 java.lang.StackOverFlowError 而当堆内存满时,抛出的java.lang.OutOfMemoryError: Java Heap Space。
  8. 相较于堆内存而言,栈内存所占空间很小。因为其在内存分配的简洁性(LIFO),栈内存分配相较于堆内存分配而言速度更快。

原创粉丝点击