jvm中除了程序计数器其他运行时区域的OutOfMemoryError

1. java堆溢出测试

java堆用于存储对象实例,只要不断创建对象,并且保证GC Roots到对象之间的可达路径来避免垃圾回收机制清理这些对象,那么当对象的达到堆的容量最大值滞后就会产生outofmemoryerror;

通过参数:-Xms20m 最小堆大小; -Xmx20m 最大堆大小;  -XX:+HeapDumpOnOutOfMemoryError  虚拟机在内存溢出异常时Dump出当前的内存堆转储快照

具体配置:

-verbose:gc -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:SurvivorRatio=8

代码:

 1 package javaTest;
 2
 3 import java.io.Serializable;
 4 import java.util.LinkedList;
 5 import java.util.List;
 6
 7 public class Portal {
 8
 9     /**
10      * vm args : -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
11      * @param args
12      */
13     public static void main(String[] args) {
14         System.out.println("test heap memory dump");
15
16
17         List<HeapOOM> lists = new LinkedList<HeapOOM>();
18
19         while(true){
20             lists.add(new HeapOOM());
21         }
22
23
24
25     }
26
27     public static class HeapOOM implements Serializable{
28
29         /**
30          *
31          */
32         private static final long serialVersionUID = -7562967142125991489L;
33
34         private int count;
35
36         public int getCount() {
37             return count;
38         }
39
40         public void setCount(int count) {
41             this.count = count;
42         }
43
44
45     }
46
47 }

异常:

注意:一定要辨别是内存泄露(memory Leak)还是内存溢出(memory Overflow)

2. java虚拟机栈和本地方法栈溢出

如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverFlowError异常;

如果虚拟机的扩展栈无法申请到足够的内存空间,则抛出OutOfMemoryError异常;

参数:-Xoss 设置本地方法栈大小;-Xss 设置虚拟机房发展大小

具体设置:

-Xss128k

代码:

 1 package javaTest;
 2
 3 public class StackOverFlowTest {
 4
 5     /**
 6      * vm args : -Xss128K
 7      * @param args
 8      */
 9     public static void main(String[] args){
10
11         OverFlowStackClass model = new OverFlowStackClass();
12
13         try{
14             model.stackLeak();
15         }catch(Throwable ex){
16             System.out.println("最大深度:"+String.valueOf(model.stackLength));
17             throw ex;
18         }
19
20
21
22
23
24
25     }
26
27     static class OverFlowStackClass{
28         public int stackLength=1;
29
30         public void stackLeak(){
31             stackLength++;
32             stackLeak();
33         }
34     }
35
36
37
38 }

异常:

如果是创建过多的线程导致内存溢出,在不减少线程数量或者更换64bit虚拟机的情况下,就只能通过减少最大堆和减少虚拟机栈容量来换取更多的线程,如果没有这方便的处理经验,这种通过增加线程挤占java虚拟机栈的方式来验证java栈的内存溢出(outofmemoryerror)的场景是很难想到的;

本人电脑是windows这里对于这种情况就不做演示了,代码实现其实就是疯狂的创建新的线程来实现。java栈的内存溢出;

3. 方法区和运行时常量池的内存溢出

String.intern();是一个Native方法,它的作用是 如果字符串常量池中已经包含一个等于此String对象的字符串,则返回字符串常量池中的这个字符串;否则创建一个新的对象,该对象添加到常量池中,最后返回此字符串的引用。

参数:-XX:PermSize  -XX:MaxPermSize

具体参数:

-XX:PermSize=10M -XX:MaxPermSize=10M

代码:

 1 package javaTest;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5
 6 public class MethodOutOfMemoryError {
 7
 8     /**
 9      * vm args: -XX:PermSize=10M -XX:MaxPermSize=10M
10      * @param args
11      */
12     public static void main(String[] args){
13
14         List<String> lists = new ArrayList<String>();
15
16         int i=0;
17         while(true){
18             lists.add(String.valueOf(i++).intern());
19         }
20
21     }
22
23 }

异常:

1.7+以上版本不会出现异常了,可以通过:-verbose:gc查看GC的回收过程;

4. 本机直接内存溢出

参数:-XX:MaxDirectMemorySize 制定可以使用的机器内存的大小

具体运行参数:

-Xmx10m -XX:MaxDirectMemorySize=10m

代码:

 1 package javaTest;
 2
 3 import java.lang.annotation.Annotation;
 4 import java.lang.reflect.Field;
 5
 6 import sun.misc.Unsafe;
 7
 8 public class DirectMemoryTest {
 9
10     private static final int _1MB = 1024*1024;
11
12     /**
13      * vm agrs: -Xmx10m -XX:MaxDirectMemorySize=10m
14      * @param args
15      * @throws IllegalAccessException
16      * @throws IllegalArgumentException
17      */
18     public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException{
19
20         System.out.println(_1MB);
21
22         Field unsafeField = Unsafe.class.getDeclaredFields()[0];
23         unsafeField.setAccessible(true);
24         Unsafe unsafe = (Unsafe)unsafeField.get(null);
25         while(true){
26             unsafe.allocateMemory(_1MB);
27         }
28
29
30
31
32     }
33 }

异常:

虽然java有垃圾回收机制,但是内存溢出对我们来说也是家常便饭,所以要明白什么情况下导致内存溢出,从而尽量避免内存溢出的发生;

如果出现内存异常根据堆栈信息可以快速排查是什么原因;

时间: 2024-11-25 21:38:48

jvm中除了程序计数器其他运行时区域的OutOfMemoryError的相关文章

JVM知识总结-运行时区域划分

区域简介 JVM运行时区域有些随着虚拟机进程的启动而存在,有些依赖于用户线程的启动和结束而建立和销毁,大致分为以下几类:方法区,虚拟机栈,本地方法栈,堆,程序计数器,概念图如下(源于<深入理解JAVA虚拟机-JVM高级特性>): 程序计数器 当前线程所执行的字节码的行号指示器,是一块各个线程私有的内存,每个线程都有一个独立的程序计数器: 如果线程执行的是一个JAVA方法,计数器记录的是虚拟机字节码指令的地址,如果执行的是一个Native方法,计数器值为空(Undefined): 唯一一个在JV

JVM学习笔记:Java运行时数据区域

JVM执行Java程序的过程中,会使用到各种数据区域,这些区域有各自的用途.创建和销毁时间.根据<Java虚拟机规范>,JVM包括下列几个运行时数据区域,如下图所示: 其中红色部分是线程私有的,即每个线程各自都有自己的一份.绿色部分是各个线程共享的. 1.PC寄存器(The pc Register) (1)每一个Java线程都有一个PC寄存器. (2)PC寄存器是用于存储每个线程下一步将执行的JVM指令,如该方法为native的,则PC寄存器中不存储任何信息. (3)此内存区域是唯一一个在JV

报错:此版本的SQL Server Data Tools与此计算机中安装的数据库运行时组件不兼容

在Visual Studio 2012中使用Entity Framework,根据模型生成数据库时,报如下错误: 无法在自定义编辑器中打开Transact-SQL文件此版本的SQL Server Data Tools与此计算机中安装的数据库运行时组件不兼容 解决办法:下载"Server Data Tools for Visual Studio 2012" ,并安装,重新启动Visual Studio 2012.

深入浅出JVM(一):运行时数据区域

程序计数器 线程私有 指向了正在执行的虚拟机字节码指令的地址:如果是本地方法,数值为空 没有 OutOfMemoryError 错误的区域 Java虚拟机栈 线程私有: 生命周期与线程相同: 代表着 Java 方法执行的内存模型:每个方法执行时的同时会创建一个栈帧(Stack Frame)用于存放局部比量表.操作数栈.动态链接.方法出口等信息. 每个方法从调用到执行完毕的过程,对应着每一个栈帧在虚拟机栈中入栈到出栈的过程. 如果线程请求的栈深度大于虚拟机允许的深度,跑出 StackOverflo

C#中CLR(公共语言运行时)与IL(中间代码)

.net平台中的CLR 首先要说明的是,.NET平台与C#不是一回事 它是C#,VB.net等程序运行的平台. CLR是公共语言运行时,是 .NET Framework的重要组成部分.它提供了内存管理.线程管理和异常处理等服务,而且还负责对代码实施严格的类型安全检查,保证了代码的正确性. 事实上,类型安全(Type Checker).垃圾回收(Garbage Collector).异常处理(Exception Manager).向下兼容(COM Marshaler)等很多C#中的特性都是由CLR

jvm(二)------各个运行时数据库常见内存溢出分析与模拟

一.堆溢出 jvm参数  -Xms11m -Xmx40m 运行代码 public static void main(String[] args) { List<byte[]> list = new ArrayList<>(); int i=0; while(true){ list.add(new byte[5*1024*1024]); System.out.println("分配次数:"+(++i)); } } 运行结果 分配次数:1 分配次数:2 分配次数:3

Jvm(9),运行时数据---独占区---虚拟机栈

一,总览 Java Virtual Machine Stacks,线程私有,生命周期与线程相同,描述的是Java方法执行的内存模型:每一个方法执行的同时都会创建一个栈帧(Stack Frame),由于存储局部变量表.操作数栈.动态链接.方法出口等信息.每一个方法的执行就对应着栈帧在虚拟机栈中的入栈,出栈过程. 我们来看一个例子 public class Demo3 { public void test1() { System.out.println("我是test1的方法"); tes

WP8.1中C++的winodws运行时组件位移操作的差异

最近学习WP8.1应用开发,想把C语言的SM3国密算法移植到手机app中.由于把C语言的代码转换成C#代码工作量较大,因此只能用winodws运行时组件来实现. SM3国密算法是一种HASH算法,具体详情请自行百度. 结果测试发现手机上SM3算法计算出来的结果和电脑上运行的结果不同!经过我一点点调试发现是位移操作惹的祸,代码中有如下宏定义: #define SHL(x,n) (((x) & 0xFFFFFFFF) << n) #define ROTL(x,n) (SHL((x),n)

Jvm(7),运行时数据---jvm运行时数据总览

jvm官方给的数据区图 首先我们来从总体上来看线程共享区和线程独占区.通过下面的图了解 其实在这里我们可以完全把运行时数据和多线程联系在一起,多线程的基础无非就是线程共享区和线程独占区的概念. 原文地址:https://www.cnblogs.com/qingruihappy/p/9691286.html