原文链接 译文链接 作者:Tai Truong 译者:Jaxon
所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?
Java内存模型在JVM specification, Java SE 7 Edition, and mainly in the chapters “2.5 Runtime Data Areas” and “2.6 Frames”中有详细的说明。对象和类的数据存储在3个不同的内存区域:堆(heap space)、方法区(method area)、本地区(native area)。
堆内存存放对象以及数组的数据,方法区存放类的信息(包括类名、方法、字段)、静态变量、编译器编译后的代码,本地区包含线程栈、本地方法栈等存放线程
方法区有时被称为持久代(PermGen)。
所有的对象在实例化后的整个运行周期内,都被存放在堆内存中。堆内存又被划分成不同的部分:伊甸区(Eden),幸存者区域(Survivor Sapce),老年代(Old Generation Space)。
方法的执行都是伴随着线程的。原始类型的本地变量以及引用都存放在线程栈中。而引用关联的对象比如String,都存在在堆中。为了更好的理解上面这段话,我们可以看一个例子:
01 |
import java.text.SimpleDateFormat;
|
02 |
import java.util.Date;
|
03 |
04 |
import org.apache.log4j.Logger;
|
05 |
06 |
public class HelloWorld {
|
07 |
private static Logger LOGGER = Logger.getLogger(HelloWorld. class .getName());
|
08 |
09 |
public void sayHello(String message) {
|
10 |
SimpleDateFormat formatter = new SimpleDateFormat( "dd.MM.YYYY" );
|
11 |
String today = formatter.format( new Date());
|
12 |
LOGGER.info(today + ": " + message);
|
13 |
}
|
14 |
} |
这段程序的数据在内存中的存放如下:
通过JConsole工具可以查看运行中的Java程序(比如Eclipse)的一些信息:堆内存的分配,线程的数量以及加载的类的个数;
这里有一份极好的白皮书:Memory Management in the Java HotSpot Virtual Machine。它描述了垃圾回收(GC)触发的内存自动管理。Java的内存结构包含如下部分:
堆内存
堆内存同样被划分成了多个区域:
- 包含伊甸(Eden)和幸存者区域(Survivor Sapce)的新生代(Young generation)
- 老年代(Old Generation)
不同区域的存放的对象拥有不同的生命周期:
- 新建(New)或者短期的对象存放在Eden区域;
- 幸存的或者中期的对象将会从Eden区域拷贝到Survivor区域;
- 始终存在或者长期的对象将会从Survivor拷贝到Old Generation;
生命周期来划分对象,可以消耗很短的时间和CPU做一次小的垃圾回收(GC)。原因是跟C一样,内存的释放(通过销毁对象)通过2种不同的GC实现:Young GC、Full GC。
为了检查所有的对象是否能够被销毁,Young GC会标记不能销毁的对象,经过多次标记后,对象将会被移动到老年代中。
哪儿的OutOfMemoryError
对内存结构清晰的认识同样可以帮助理解不同OutOfMemoryErrors:
Exception in thread “main”: java.lang.OutOfMemoryError: Java heap space
Exception in thread “main”: java.lang.OutOfMemoryError: PermGen space
原因:类或者方法不能被加载到老年代。它可能出现在一个程序加载很多类的时候,比如引用了很多第三方的库;
Exception in thread “main”: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
原因:创建的数组大于堆内存的空间
Exception in thread “main”: java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?
原因:分配本地分配失败。JNI、本地库或者Java虚拟机都会从本地堆中分配内存空间。
Exception in thread “main”: java.lang.OutOfMemoryError: <reason> <stack trace>(Native method)
原因:同样是本地方法内存分配失败,只不过是JNI或者本地方法或者Java虚拟机发现;
关于OutOfMemoryError的更多信息可以查看:“Troubleshooting Guide for HotSpot VM”, Chapter 3 on “Troubleshooting on memory leaks”
参考链接:
- Provides Java HotSpot information about VM Options and environment variables
-
Troubleshooting Guide for HotSpot VM
An exhaustive guide for memory leaks, system crashes, hangings, loops, signal and exception handling. -
Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
Ergonomics and tuning goals, generations sizing using VM arguments. -
Thanks for the memory – Understanding how the JVM uses native memory on Windows and Linux
Explains how the memory in the JVM like the heap is memory into the RAM on different operating systems and CPUs (32/64bit). -
Java Micro Edition – Tuning
Describes runtime options to adjust performance in the Java ME edition. It also illustrates the compilation of bytecode into native code. - Summary of Sun’s document “Tuning Garbage collection with the 1.4.2 Hotspot JVM”.
- Discussion about where references and objects are stored in the JVM.
相关推荐
Java内存模型是Java虚拟机规范中定义的一部分,它规定了Java程序中变量的读写行为,以及线程之间的交互规则。理解Java内存模型对于编写正确、高效的多线程程序至关重要。在Java 5之前,Java内存模型的描述比较模糊,...
### Java内存模型详解 #### 1. JMM简介 ##### i. 内存模型概述 Java内存模型(Java Memory Model, JMM)是Java虚拟机(JVM)的一部分,用于规定程序中的各种变量(包括实例字段、静态字段和数组元素等)在多个...
1. **内存层次结构**:Java 内存模型将内存分为堆内存、栈内存、方法区(在 Java 8 及以后版本中被元空间替代)和程序计数器等几个区域,其中堆存储对象实例,栈存储局部变量,方法区存储类信息,程序计数器则用于...
Java内存模型(JVM Memory Model,简称JMM)是Java平台中的一个重要概念,它定义了程序中各个变量的访问规则,以及在多线程环境下的内存一致性效果。JMM主要解决的是并发环境下不同线程之间如何共享数据以及如何保证...
标题和描述中提及的知识点主要围绕Java内存模型(JMM),JVM内存结构,包括堆栈讲解,以及本机内存管理等内容。以下是对这些知识点的详细阐述: ### Java内存模型(JMM) #### JMM简介 Java内存模型(JMM)是Java虚拟机...
Java内存模型是Java平台的核心概念之一,它定义了Java程序中各种变量的访问规则以及如何在运行时分配内存区域给对象。Java内存模型的深入分析对于编写高性能的Java应用程序至关重要,本文将详细探讨Java内存模型的...
Java 内存模型的抽象 4 重排序 6 处理器重排序与内存屏障指令 7 happens-before 10 重排序 13 数据依赖性 13 as-if-serial 语义 13 程序顺序规则 15 重排序对多线程的影响 15 顺序一致性 19 数据竞争与顺序...
Java内存模型(Java Memory Model, JMM)是Java平台中用于规范线程间通信和内存可见性的重要概念,它的目标是确保多线程环境下的正确同步。然而,原始的JMM存在一些严重的缺陷,导致了开发者在理解和实现线程安全时...
Java内存模型(JVM Memory Model,简称JMM)是Java平台中的一个重要概念,它定义了在多线程环境下,如何在共享内存中读写数据,以及如何保证数据的一致性和可见性。本教程《深入理解JAVA内存模型》将带你深入探讨这...
Java内存模型(JMM)是Java虚拟机(JVM)规范的一部分,用于定义多线程环境下共享变量的访问规则和操作的可见性。本文将对Java内存模型进行知识汇总,帮助读者更好地理解和掌握相关知识点。 首先,内存模型的概念是...
Java内存模型,简称JMM(Java Memory Model),是Java虚拟机规范中定义的一个抽象概念,它描述了在多线程环境下,如何保证共享数据的正确性。深入理解JMM对于编写高效、线程安全的Java代码至关重要。 首先,我们要...
Java内存模型中还涉及到对象的创建和初始化过程,其中涉及到构造函数和初始化块。当一个类的对象被实例化时,JVM会调用相应的构造函数,按照声明顺序执行所有成员变量和初始化块,最终将对象的状态初始化到一个合法...
Java内存模型(JMM)与JVM内存结构不同,它是针对多线程环境下内存访问的抽象模型。JMM确保在多线程环境下,共享变量的读写操作具有正确的顺序和可见性,通过volatile、synchronized等关键字来实现这一目标。JMM关注...
《深入Java内存模型》是一本面向Java开发人员的专业书籍,旨在帮助读者深入理解Java平台的内存管理和性能优化。这本书详细探讨了Java内存模型(JVM)的基础知识,以及如何利用这些知识来提升程序的效率和稳定性。...
8. Java内存模型与JVM内存结构的关系:虽然两者名字相似,但JMM关注的是线程间的通信和同步,而JVM内存结构则更多地涉及堆、栈、方法区等内存区域的划分。 在实际编程中,理解并合理应用Java内存模型,可以帮助我们...