所有的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”
相关推荐
主要为大家讲解JVM内存模型|内存结构|内存屏障,他们的概念,有什么关联以及各种的功能
一、JVM整体结构及内存模型 二、JVM内存参数设置 三、逃逸分析
jvm的内存结构图,详细的介绍了jvm运行的模型流程,包括jvm运行的五大内存分布。通过什么是jvm什么是java编程程序的=中的三个兄弟jdk.jvm和jre的区别
jvm的内存结构图的ppt模型分析.zip
了解Jvm的发展历程即结构,讲解jvm的结构、内存模型、类加载机制,gc的算法分类、class文件的类型
JVM内存结构Java 代码是要运行在虚拟机上的,而虚拟机在执行 Java 程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途。如果
2019最新深入理解JVM内存结构及运行原理(JVM调优)高级核心课程视频教程下载。JVM是Java知识体系中的重要部分,对JVM底层的了解是每一位Java程序员深入Java技术领域的重要因素。本课程试图通过简单易懂的方式,系统...
文件总结了JVM的体系结构:四大块,类装载子系统(class loader subsystem),执行引擎子系统(Executionengine子系统),垃圾回收系统(gc),运行时数据区(JVM内存)。
作为一个三个多月没有去工作的独立开发者而言,今天去小米面试了一把.怎么说呢,无论你水平如何,...对于开发者来说,存储器的层次结构应该是非常熟悉的,大体如下:其中寄存器,L1,L2,L3都被封装在CPU芯片中,作为应用开发者而
1、以上是Java虚拟机规范,不同的虚拟机实现会各有不同,但是一般会遵守规范 2、规范中定义的方法区,只是一种概念上的区域,并说明了其应该具有什么功能 3、不同
此文对于java初学者,想了解清楚java内存结构的童鞋,很有参考价值
1、以上是Java虚拟机规范,不同的虚拟机实现会各有不同,但是一般会遵守规范 2、规范中定义的方法区,只是一种概念上的区域,并说明了其应该具有什么功能 3、不同
Java内存模型详解,JVM结构..
JVM体系架构,主要介绍JVM 内存模型。
第4节jvm初体验-内存溢出问题的分析与解决 [免费观看] 00:17:59分钟 | 第5节jvm再体验-jvm可视化监控工具 [免费观看] 00:21:17分钟 | 第6节杂谈 [免费观看] 00:12:37分钟 | 第7节Java的发展历史00:27:24分钟 | ...
* 在内存结构章节,能够学习掌握 JVM内存溢出现象,堆栈内存结构,利用内存诊断工具排查问题。彻底分析 StringTable的相关知识与性能优化,掌握直接内存分配原理和释放手段。 * 在垃圾回收章节,不仅会介绍垃圾回收...
一套完整介绍java内存模型和内存结构的文档
介绍JVM的内部结构、启动流程以及内存模型。并介绍JVM字节码的执行方式。 第三课 常用JVM参数 堆的分配参数 栈分配及实例讲解 server与client模式 调试跟踪参数 介绍常用的JVM参数,包括内存分配、堆栈分配、...
非常好的HM JVM课件,尤其是字节码的部门,非常良心,搭配HM JVM视频使用更加哦。博客地址https://blog.csdn.net/hancoder/article/details/105210258