笔记:深入理解JVM 第2章 Java内存区域与内存溢出
来源:互联网 发布:java 模拟post请求 编辑:程序博客网 时间:2024/06/02 03:35
1、JVM 运行时数据区
所有线程共享的数据区:方法区(持久代)、堆区
线程隔离的数据区:程序计数器、Java虚拟机栈区
堆区构成:新生代 ( 由Eden, From Survivor, To Survivor 构成)、老生代
运行时常量池:方法区一部分,用于存放编译期生成的各种字面量和符号引用
直接内存:不是JVM 运行时数据区的一部分,不受Java堆大小限制,但是受物理内存限制,也会抛出 OutOfMemoryError。Java NIO 中的DirectByteBuffer 使用了直接内存。
2、OutOfMemoryError 案例
(1)、堆溢出
在对象数量达到最大堆容量限制后,发生堆内存溢出异常 OutOfMemoryError: Java heap space 。
JVM配置:
-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
代码:
public static void main(String[] args) { List<Object> list = new LinkedList<Object>(); for(int i=0;i<Long.MAX_VALUE;i++) { list.add(new XX()); }}
输出:
java.lang.OutOfMemoryError: GC overhead limit exceededDumping heap to java_pid4192.hprof ...Heap dump file created [37582435 bytes in 0.265 secs]Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceededat java.util.LinkedList.linkLast(Unknown Source)at java.util.LinkedList.add(Unknown Source)at chapter2.HeapOver.main(HeapOver.java:14)
使用Eclipse Memory Analyzer 分析生成的Dump文件:java_pid4192.hprof
快照
(2).栈溢出
线程的请求栈深度大于虚拟机所允许最大深度,将抛出StackOverflowError
如果虚拟机在扩展栈时候无法申请得到足够的内存空间,将抛出OutOfMemoryError
JVM配置:
-Xss128k
public class StackOverExam1 {public int stackLength = 1;public void methed1() {System.out.println("Stack Length:" + stackLength++);if(stackLength < Long.MAX_VALUE) { methed1(); }}public static void main(String[] args) {StackOverExam1 exam = new StackOverExam1();exam.methed1();}}
抛出异常:
Stack Length:987Stack Length:988Exception in thread "main" java.lang.StackOverflowErrorat java.nio.Buffer.<init>(Unknown Source)at java.nio.CharBuffer.<init>(Unknown Source)at java.nio.HeapCharBuffer.<init>(Unknown Source)at java.nio.CharBuffer.wrap(Unknown Source)at sun.nio.cs.StreamEncoder.implWrite(Unknown Source)at sun.nio.cs.StreamEncoder.write(Unknown Source)
在单线程下,无论是栈帧太大还是虚拟机容量太小,当内存无法分配时候,虚拟机抛出的都是StackOverflowError。
多线程情况下,-Xss设置得越大,即为每个线程栈分配内存越大,越容易抛出 OutOfMemoryError: unable to create new native thread
-Xss2m
多线程代码:
public static void main(String[] args) { for(long i=0;i<Long.MAX_VALUE;i++){System.out.println("Thread Num:"+ (++i));new Thread(new Runnable(){@Overridepublic void run() {while(true){}}}).start();}}
抛出异常:
ava.lang.OutOfMemoryError: unable to create new native thread
(3). 对象常量池和方法区溢出
抛出 OutOfMemory: PermGen space
常量池溢出例子:
String.intern() 是一个Native方法,其作用是:若字符串常量池包含此String对象,则返回该对象;否则将其加入到常量池中,再返回。
JVM配置:
-XX:PermSize=10m -XX:MaxPermSize=10m代码:
public class RuntimeConstPoolOver { public static void main(String[] args) {List<String> list = new LinkedList<String>();for (int i = 0; i < Long.MAX_VALUE; i++) {//System.out.println(i);list.add(String.valueOf(i).intern());}}}
JDK1.6 输出:
java.lang.OutOfMemoryError: PermGen spaceJDK 1.7 不会有错误
方法区溢出例子:
Spring、Hibernate 等框架会使用CGLib技术,将动态生成的Class载入方法区,当方法区太小时,引发
java.lang.OutOfMemoryError: PermGen space
(4).直接内存溢出
DirectMemory 容量可通过 -XX: MaxDirectMemorySize 制定,若无制定则与JVM堆的最大值(-Xmx) 一样。
判断是否由DirectMemory的溢出条件:
a. Heap Dump 文件不会看到明显异常,文件很小
b. 程序中直接或间接使用了NIO
例子JVM配置:
-Xmx20M -XX:MaxDirectMemorySize=20M
import java.lang.reflect.Field;import sun.misc.Unsafe;public class DirectMemoryOver {public static void main(String[] args) throws IllegalArgumentException,IllegalAccessException {long _100M = 100 * 1024 * 1024;Field f = Unsafe.class.getDeclaredFields()[0];f.setAccessible(true);Unsafe unsafe = (Unsafe) f.get(null);for (int i = 0; i < Long.MAX_VALUE; i++) { System.out.println(i);unsafe.allocateMemory(_100M);}}}
输出:
126Exception in thread "main" java.lang.OutOfMemoryErrorat sun.misc.Unsafe.allocateMemory(Native Method)at chapter2.DirectMemoryOver.main(DirectMemoryOver.java:17)
- 笔记:深入理解JVM 第2章 Java内存区域与内存溢出
- 第2章 Java内存区域与内存溢出异常--《深入理解 Java 虚拟机》笔记
- [课本划重点]深入理解jvm-第2章 java内存区域与内存溢出异常(1)
- 《深入理解Java虚拟机》第2章 Java内存区域与内存溢出异常
- 《深入理解Java虚拟机》读书笔记(1)---第2章 Java内存区域与内存溢出异常
- 深入理解JVM笔记一-java内存区域与内存溢出异常
- 【深入理解JVM】第2章 JVM内存分布与溢出 笔记
- java---《深入理解java虚拟机》第二章【java内存区域与内存溢出异常】阅读笔记
- 读书笔记——深入理解java虚拟机第2章(java内存区域与内存溢出异常)
- 深入理解JVM虚拟机学习笔记(—)内存区域与内存溢出异常
- 深入理解JVM读书笔记一: Java内存区域与内存溢出异常
- 深入理解JVM——java内存区域与内存溢出异常
- 深入理解JVM之Java内存区域与内存溢出异常
- 深入理解JVM之内存区域与内存溢出
- 深入理解JVM之内存区域与内存溢出
- 深入理解 Java 虚拟机-Java 内存区域与内存溢出
- 深入理解JVM(2)——内存区域与内存溢出
- [深入理解java虚拟机]:内存区域与内存溢出
- 黑马程序员——TreeSet集合储存自定义对象
- 雷观(十五):提高生产力和程序员价值的2种方法
- 冒泡排序
- Android -- 采用系统相册浏览指定路径下照片
- Java 应用程序 访问配置文件
- 笔记:深入理解JVM 第2章 Java内存区域与内存溢出
- git的工作流程
- 响应XUL元素的resize事件
- 结构型模式之Facade模式
- android开发之自定义dialog及dialog替换activity好处
- mongodb+nodejs
- iOS开发--好用的第三方库(OC)<持续更新>
- AngularJS form $addControl 注册控件control
- #1082 : 然而沼跃鱼早就看穿了一切