java 多线程内存模型

时间:2022-09-28 20:51:58

并发编程网 - ifeve.com

让天下没有难学的技术

JAVA的内存模型及结构

原文链接   译文链接  作者:Tai Truong    译者:Jaxon

所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?

Java内存模型

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)。

堆内存存放对象以及数组的数据,方法区存放类的信息(包括类名、方法、字段)、静态变量、编译器编译后的代码,本地区包含线程栈、本地方法栈等存放线程

java 多线程内存模型

方法区有时被称为持久代(PermGen)。

java 多线程内存模型

所有的对象在实例化后的整个运行周期内,都被存放在堆内存中。堆内存又被划分成不同的部分:伊甸区(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 = newSimpleDateFormat("dd.MM.YYYY");
11         String today = formatter.format(new Date());
12         LOGGER.info(today + ": " + message);
13     }
14 }

这段程序的数据在内存中的存放如下:

java 多线程内存模型

通过JConsole工具可以查看运行中的Java程序(比如Eclipse)的一些信息:堆内存的分配,线程的数量以及加载的类的个数;

java 多线程内存模型

 Java内存结构

这里有一份极好的白皮书:Memory Management in the Java HotSpot Virtual Machine。它描述了垃圾回收(GC)触发的内存自动管理。Java的内存结构包含如下部分:

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”

 

参考链接:

 

原创文章,转载请注明: 转载自并发编程网 – ifeve.com

本文链接地址: JAVA的内存模型及结构

4 java 多线程内存模型

Jaxon

Related Posts:

  1. JVM实用参数(四)内存调优 
  2. 最简单例子图解JVM内存分配和回收 
  3. JVM实用参数系列 
  4. 在java 7中捕获多个异常 
  5. 为什么我的JVM能实际使用的内存比-Xmx指定的少? 
  6. JVM的持久代——何去何从? 
  7. JVM实用参数(八)GC日志 
  8. 面向GC的Java编程 
  9. 并发工具类(二)同步屏障CyclicBarrier 
  10. 并发工具类(一)等待多线程完成的CountDownLatch 
  11. 测试并发应用(五) 编写有效的日志 
  12. Java PermGen 去哪里了? 
  13. 《JVM故障诊断指南》之1 —— JVM概览与介绍 
  14. JVM性能优化, Part 5:Java的伸缩性 
  15. 五个改善你服务器日志的技术 
  • Trackback 关闭
  • 评论 (0)
  1. 暂无评论

您必须 登陆 后才能发表评论 

Velocity官方指南-简介

无锁有序链表的实现

本站服务器由UCloud云服务赞助


近期文章

热门文章

近期评论

标签

actor Basic cacheline classes collectionsconcurrency Concurrentconcurrent data structure ConcurrentHashMapCustomizing design Executor Executor framework False Sharing faq fork Fork/Join fork join Framework Functional ProgrammingGuava IO JAVA java8 jmm join JVMlock Memory Barriers Netty NIO OAuth 2.0pattern-matching quartz RingBuffer ScalaSemaphore stm Storm synchronizationSynchronized thread tomcat volatile 多线程

文章归档

友情链接

分类目录

java 多线程内存模型 感谢又拍云为本站提供服务器和图片服务。

return top