JVM—内存溢出、OutOfMemoryError、StackOverflowError
学习jvm时看到几篇非常好的系列文章,转载了:
一、概要
我们可以带着以下几个问题去学习自动内存管理机制,罗列如下:
- 什么操作可能导致内存溢出?
- 有哪些种类的内存溢出?
- 都是在内存的哪些区域溢出?
二、运行时数据区域
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域,如下图所示
其中虚拟机栈、本地方法栈和程序技术器是线程私有的,方法区和堆是线程共享的.
2.1程序计数器
作用:当前线程所执行的字节码的行号指示器
- 字节码解释器工作时通过改变它的值来选取下一条需要执行的字节码指令
- 分支、循环、跳转、异常处理和线程恢复都依赖于它
2.2虚拟机栈
栈的作用:栈用于存储局部变量表、操作数栈、动态链接和方法出口等信息.
其中局部变量表用于存放8种基本数据类型(boolean,byte,char,short,int,float,long,double)和reference类型.
reference类型:
指向对象起始地址的引用指针
指向一个代表对象的句柄
指向一条字节码指令的地址
可抛出两种异常状况
线程请求的栈深度大于虚拟机所允许的栈深度,抛出StackOverflowError异常
当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常是
2.3本地方法栈
与虚拟机栈的作用非常相似.其区别是虚拟机栈执行Java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务
同时也会抛出StackOverflowError和OutOfMemoryError异常
2.4堆
堆的作用:分配所有的对象实例和数组。可以抛出OutOfMemoryError异常。
2.5方法区
方法区的作用:用于存储已被虚拟机加载的类信息(Class)、常量(final修饰)、静态变量(static)和即时编译器编译后的代码(code)
可以抛出OutOfMemoryError异常
2.6运行时常量池
属于方法区的一部分,用于存放编译期生成的各种字面量和符号引用(在以后介绍Class结构会讲到),在类加载后存放到方法区的运行时常量池中。可抛出OutOfMemoryError异常
三、对象访问
主流的两种访问方式:使用句柄和直接指针。(HotSpot虚拟机就是使用直接指针的访问方式)
使用句柄访问
四、OutOfMemoryError异常
在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError异常的可能.
下面通过若干实例来验证异常发生的场景.以下代码的开头都注释了执行时所需要设置的虚拟机启动参数,这些参数对实验结果有直接影响,请调试代码的时候不要忽略掉.
4.1Java堆溢出
堆里放的是new出来的对象,所以这部分很简单不断的new对象就可以了,但是为了防止对象new出来之后被GC,所以把对象new出来的对象放到一个List中去即可。为了有更好的效果,可以在运行前,调整堆的参数。
- import java.util.ArrayList;
- import java.util.List;
- /**
- * VM Args: -Xms20m -Xms20m - XX:+HeapDumpOnOutOfMemoryError
- * @author Administrator
- *
- */
- public class HeapOOM {
- static class OOMObject{}
- public static void main(String[] args) {
- List<OOMObject> list = new ArrayList<HeapOOM.OOMObject>();
- while(true ){
- list.add( new OOMObject());
- }
- }
- }
运行结果
4.2虚拟机栈溢出
- 在单线程的堆中我们不断的让一个成员变量自增,容纳这个变量的单元无法承受这个变量了,就抛出StackOverflowError了。
- 可以开尽量多的线程,并在每个线程里调用native的方法,就自然会抛出 OutOfMemoryError了。
- /**
- * VM Args: - Xss64k
- * @author Administrator
- *
- */
- public class JavaVMStackSOF {
- private int stackLength = 1;
- public void stackLeak(){
- stackLength ++;
- stackLeak();
- }
- public static void main(String[] args) throws Throwable {
- JavaVMStackSOF oom = new JavaVMStackSOF();
- try{
- oom.stackLeak();
- } catch(Throwable e){
- System. out.println("Stack length:" + oom.stackLength);
- throw e;
- }
- }
- }
运行结果
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodProxy;
- /**
- * VM Args:- XX:PermSize=10m -XX:MaxPermSize=10m
- * @author Administrator
- *
- */
- public class JavaMethodAreaOOM {
- public static void main(String[] args) {
- while (true ){
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(OOMObject. class );
- enhancer.setUseCache( false );
- enhancer.setCallback( new MethodInterceptor() {
- @Override
- public Object intercept(Object obj, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- return proxy.invoke(obj, args);
- }
- });
- enhancer.create();
- }
- }
- static class OOMObject{
- }
- }
4.4 运行时常量池溢出
- import java.util.ArrayList;
- import java.util.List;
- /**
- * VM Args:- XX:PermSize=10m -XX:MaxPermSize=10m
- * @author Administrator
- *
- */
- public class RuntimeConstantPoolOOM {
- public static void main(String[] args) {
- List<String> list = new ArrayList<String>();
- int i = 0;
- while (true ){
- list.add(String. valueOf(i++).intern());
- }
- }
- }
相关引用:
JVM—内存溢出、OutOfMemoryError、StackOverflowError的更多相关文章
- JVM内存溢出分析java.lang.OutOfMemoryError: Java heap space
JVM内存溢出查询java.lang.OutOfMemoryError: Java heap space查出具体原因分为几个预备步骤 1.在运行java程序是必须设置jvm -XX:+HeapDump ...
- jvm内存溢出分析
概述 jvm中除了程序计数器,其他的区域都有可能会发生内存溢出 内存溢出是什么? 当程序需要申请内存的时候,由于没有足够的内存,此时就会抛出OutOfMemoryError,这就是内存溢出 内存溢出和 ...
- jvm内存溢出问题
Java内存溢出详解 一.常见的Java内存溢出有以下三种: 1. java.lang.OutOfMemoryError: Java heap space ----JVM Heap(堆)溢出 J ...
- jvm 内存溢出问题排查方法
如果你做TCP通讯或者map集合操作,并发处理等功能时,很容易出现 Java 内存溢出的问题.本篇文章,带领大家深入jvm,分析并找出jvm内存溢出的代码. jvm中除了程序计数器,其他的区域都有可能 ...
- JVM 内存溢出详解(栈溢出,堆溢出,持久代溢出、无法创建本地线程)
出处: http://www.jianshu.com/p/cd705f88cf2a 1.内存溢出和内存泄漏的区别 内存溢出 (Out Of Memory):是指程序在申请内存时,没有足够的内存空间供 ...
- JVM 内存溢出 实战 (史上最全)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- Tomcat中JVM内存溢出及合理配置及maxThreads如何配置(转)
来源:http://www.tot.name/html/20150530/20150530102930.htm Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚 ...
- Tomcat中JVM内存溢出及合理配置
Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识 ...
- JVM内存溢出及合理配置
Tomcat本身不能直接在计算机上运行,需要依赖于硬件基础之上的操作系统和一个Java虚拟机.Tomcat的内存溢出本质就是JVM内存溢出,所以在本文开始时,应该先对Java JVM有关内存方面的知识 ...
- 巧解Tomcat中JVM内存溢出问题
你对Tomcat 的JVM内存溢出问题的解决方法是否了解,这里和大家分享一下,相信本文介绍一定会让你有所收获. tomcat 的JVM内存溢出问题的解决 最近在熟悉一个开发了有几年的项目,需要把数据库 ...
随机推荐
- mybatis插入一个对象后获取表中自增的主键Id并且传入到插入的的对象中,方便将对象中其他属性赋值给其他以前表主键Id作为非空字段的表
原本的sql语句为: <insert id="xx" parameterType="com.hrt.partner.model.ShopInsert"&g ...
- Effective Java 第三版——77. 不要忽略异常
Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...
- C# 批量图片打包下载
实现点击下载功能,可以一次性下载多个附件.具体实现代码如下 : private void Com_XZTP_FJ(string maiId, string wtfjdz, string CLwtfjd ...
- Atitit 数据库排除某一列 字段 显示
Atitit 数据库排除某一列 字段 显示 GROUP_CONCAT 行列转换 mysql利用group_concat()合并多行数据到一行_Mysql_脚本之家 sELECT GROUP_CO ...
- [rook] rook的控制流
以下是rook为一个pod准备可用块存储的过程: 1. rook operator运行,并且在k8s每台机器上运行一个rook agent的pod: 2. 用户创建一个pvc,并指定storagecl ...
- 2018年中国C++大会详细日程+报名
http://purecpp.org/detail?id=2050
- SqlServer 行转一列逗号隔开
SELECT STUFF( (SELECT ',' + convert(varchar(10),PID) FROM tt WHERE a='老王' FOR xml path('') ),1,1,'' ...
- SetProcessWorkingSetSize减少内存占用
[DllImport("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize")] public stat ...
- centos6.5上安装ftp服务
这是之前搭建过,但没记录,因为昨天使用人过来说使用有问题,突然发现没有记录,好心慌,现在的记忆真的只有1周而已,穷和老都是原罪啊!! 环境准备:centos6.5 vm 安装ftp:
- ubuntu源码安装jdk8
最近学习java,想起来没有在Ubuntu上使用过 因此想安装下环境,并在Ubuntu上试用MPXJ读取mpp文件 1.安装 下载jdk8 https://www.oracle.com/technet ...