从几个sample来学习Java堆,方法区,Java栈和本地方法栈
2019独角兽企业重金招聘Python工程师标准>>>
最近在看《深入理解Java虚拟机》,书中给了几个例子,比较好的说明了几种OOM(OutOfMemory)产生的过程,大部分的程序员在写程序时不会太关注Java运行时数据区域的结构:
感觉有必要通过几个实在的例子来加深对这几个区域的了解
1)Java堆
所有对象的实例分配都在Java堆上分配内存,堆大小由-Xmx和-Xms来调节,sample如下所示:
- public class HeapOOM {
- static class OOMObject{}
- /**
- * @param args
- */
- public static void main(String[] args) {
- List<OOMObject> list = new ArrayList<OOMObject>();
- while(true){
- list.add(new OOMObject());
- }
- }
- }
public class HeapOOM {static class OOMObject{}/*** @param args*/public static void main(String[] args) {List<OOMObject> list = new ArrayList<OOMObject>();while(true){list.add(new OOMObject());}}}
加上JVM参数-verbose:gc -Xms10M -Xmx10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError,就能很快报出OOM:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
并且能自动生成Dump。
2)方法区
方法区是存放虚拟机加载类的相关信息,如类、静态变量和常量,大小由-XX:PermSize和-XX:MaxPermSize来调节,类太多有可能撑爆永久带:
- public class MethodAreaOOM {
- static class OOMOjbect{}
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- while(true){
- Enhancer eh = new Enhancer();
- eh.setSuperclass(OOMOjbect.class);
- eh.setUseCache(false);
- eh.setCallback(new MethodInterceptor(){
- @Override
- public Object intercept(Object arg0, Method arg1,
- Object[] arg2, MethodProxy arg3) throws Throwable {
- // TODO Auto-generated method stub
- return arg3.invokeSuper(arg0, arg2);
- }
- });
- eh.create();
- }
- }
- }
public class MethodAreaOOM {static class OOMOjbect{}/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubwhile(true){Enhancer eh = new Enhancer();eh.setSuperclass(OOMOjbect.class);eh.setUseCache(false);eh.setCallback(new MethodInterceptor(){@Overridepublic Object intercept(Object arg0, Method arg1,Object[] arg2, MethodProxy arg3) throws Throwable {// TODO Auto-generated method stubreturn arg3.invokeSuper(arg0, arg2);}});eh.create();}}}
加上永久带的JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后会报如下异常:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
静态变量或常量也会有可能撑爆方法区:
- public class ConstantOOM {
- /**
- * @param args
- */
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- List<String> list = new ArrayList<String>();
- int i=0;
- while(true){
- list.add(String.valueOf(i++).intern());
- }
- }
- }
public class ConstantOOM {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubList<String> list = new ArrayList<String>();int i=0;while(true){list.add(String.valueOf(i++).intern());}}}
同样加上JVM参数:-XX:PermSize=10M -XX:MaxPermSize=10M,运行后报如下异常:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space
3)Java栈和本地方法栈
栈是存放线程调用方法时存储局部变量表,操作,方法出口等与方法执行相关的信息,栈大小由Xss来调节,方法调用层次太多会撑爆这个区域,samples如下所示:
- package com.cutesource;
- public class StackOOM {
- /**
- * @param args
- */
- private int stackLength = 1;
- public void stackLeak(){
- stackLength++;
- stackLeak();
- }
- public static void main(String[] args) throws Throwable{
- // TODO Auto-generated method stub
- StackOOM oom = new StackOOM();
- try{
- oom.stackLeak();
- }catch(Throwable err){
- System.out.println("Stack length:" + oom.stackLength);
- throw err;
- }
- }
- }
package com.cutesource;public class StackOOM {/*** @param args*/private int stackLength = 1;public void stackLeak(){stackLength++;stackLeak();}public static void main(String[] args) throws Throwable{// TODO Auto-generated method stubStackOOM oom = new StackOOM();try{oom.stackLeak();}catch(Throwable err){System.out.println("Stack length:" + oom.stackLength);throw err;}}}
设置JVM参数:-Xss128k,报出异常:
Exception in thread "main" java.lang.StackOverflowError
打印出Stack length:1007,这里可以看出,在我的机器上128k的栈容量能承载深度为1007的方法调用。当然报这样的错很少见,一般只会出现无限循环的递归中,另外,线程太多也会占满栈区域:
- package com.cutesource;
- public class StackOOM {
- /**
- * @param args
- */
- private int stackLength = 1;
- private void dontStop(){
- while(true){
- try{Thread.sleep(1000);}catch(Exception err){}
- }
- }
- public void stackLeakByThread(){
- while(true){
- Thread t = new Thread(new Runnable(){
- @Override
- public void run() {
- // TODO Auto-generated method stub
- dontStop();
- }
- });
- t.start();
- stackLength++;
- }
- }
- public static void main(String[] args) throws Throwable{
- // TODO Auto-generated method stub
- StackOOM oom = new StackOOM();
- try{
- oom.stackLeakByThread();
- }catch(Throwable err){
- System.out.println("Stack length:" + oom.stackLength);
- throw err;
- }
- }
- }
package com.cutesource;public class StackOOM {/*** @param args*/private int stackLength = 1;private void dontStop(){while(true){try{Thread.sleep(1000);}catch(Exception err){}}}public void stackLeakByThread(){while(true){Thread t = new Thread(new Runnable(){@Overridepublic void run() {// TODO Auto-generated method stubdontStop();}});t.start();stackLength++;}}public static void main(String[] args) throws Throwable{// TODO Auto-generated method stubStackOOM oom = new StackOOM();try{oom.stackLeakByThread();}catch(Throwable err){System.out.println("Stack length:" + oom.stackLength);throw err;}}}
报出异常:Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread
不过在windows上运行这个例子要小心,会出现系统假死的情况,有可能需要重启机器才行。
以上几个例子虽然比较简单,但能很好帮助普通的程序员更加直观的了解Java堆,方法区,Java栈和本地方法栈。
转载于:https://my.oschina.net/Chaos777/blog/308525
从几个sample来学习Java堆,方法区,Java栈和本地方法栈相关推荐
- 46栈内存溢出、内存区域(程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区、直接内存、内存溢出)与内存溢出(对象实例化分析)
46.什么情况下会发生栈内存溢出 46.1.Java 内存区域与内存溢出 46.1.1.内存区域 46.1.1.1.程序计数器 46.1.1.2.Java 虚拟机栈 46.1.1.3.本地方法栈 46 ...
- Java堆溢出,虚拟机栈和本地方法栈溢出
Java堆溢出 JVM运行时分区的堆区是占比最大的,它用来存储对象的,每当我们new一个对象,而且要保证这个对象到GC Roots 那些对象是有路径可达的(不可达就有很大可能性被清除),那么当对象的数 ...
- 11.JDK8内存模型、本地方法栈、虚拟机栈、栈帧结构(局部变量表、操作数栈、方法出口、虚拟机栈与本地方法栈的关系、寄存器、方法区、堆(Heap)、jvm中的常量池、Metaspace(元空间))
11.JDK8内存模型 11.1.本地方法栈(Native Method Stacks) 11.2.虚拟机栈(Java Virtual Machine Stacks) 11.3.栈帧结构 11.3.1 ...
- java方法区超详细汇总,方法区到底是干什么用的?不懂方法区不能说了解jvm!
目录 一.运行时数据区结构图 二.栈.堆.方法区的交互关系 三.方法区的理解 官方文档 方法区在哪里 方法区的基本理解 HotSpot中方法区的演进 四.设置方法区大小与OOM 设置方法区内存的大小 ...
- 常量池在堆还是方法区_第九章_方法区
方法区 栈.堆.方法区的交互关系 这次所讲述的是运行时数据区的最后一个部分--方法区 从线程共享与否的角度来看 ThreadLocal:如何保证多个线程在并发环境下的安全性?典型应用就是数据库连接管理 ...
- java 本地方法栈_Java虚拟机栈和本地方法栈
Java虚拟机栈的特征 线程私有 后进先出(LIFO)栈 存储栈帧,支持Java方法的调用.执行和退出 可能出现OutOfMemoryError异常和StackOverflowError异常 Java ...
- 12.JDK1.8 JVM运行时数据区域概览、各区域介绍、程序计数器、Java虚拟机栈、本地方法栈、堆、堆空间内存分配(默认情况下)、字符串常量池、元数据区、jvm参数配置
12.JDK1.8 JVM运行时数据区域概览 12.1.JDK1.8 JVM运行时数据区域概览 12.2.各区域介绍 12.3.各区域介绍 12.3.1.程序计数器 12.3.2.Java虚拟机栈 1 ...
- 栈和堆的区别是什么? 为什么说栈的速度快,堆的速度慢?
栈与堆都是Java用来在Ram中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆. Java的堆是一个运行时数据区,类的(对象从中分配空间.这些对象通过new.new ...
- Java堆转储Dump文件的几种方法,java高级程序员面试笔试
jmap -dump:live,format=b,file=/tmp/dump.hprof 12587 我们可以通过使用jps命令轻松获得Java进程的pid. 请记住,jmap是作为实验工具引入JD ...
最新文章
- PICRUSt:16S预测宏基因组-扩增子分析锦上添花
- layer重复弹出(layui弹层同时存在多个)的解决方法
- 文件上传打满服务器带宽,文件上传云服务器 带宽选择
- sql多层嵌套别名无效_SQL之复杂查询
- I.MX6 隐藏电池图标
- 使用 Spring Boot Security 进行安全控制
- javacript Function parameters(函数参数)
- 扫雷计算机教案,《扫雷游戏》教学设计
- 我是WPF菜鸟之(4)---关于XAML与逻辑代码
- FFmpeg之YUV排列方式(十六)
- 用VAE(variational autoencoder)做sentence embedding/representation或者其他任何结构数据的热presentation...
- swwht(canvas).demo
- 英语在线听力翻译器_英语听力翻译器在线翻译PC版-英语听力翻译电脑版下载 v2.1.4--PC6电脑版...
- 裁员的第一波枪声,从游戏行业响起了?
- 解决git命令You must use a personal access token or SSH key的问题
- “犯强汉者,虽远必诛!”----遥想伟大汉人当年
- verilog分频电路
- Latex texstudio法国人名字上面的一撇,声调输入
- MAC 升级monterey 系统后无法启动Parallels Desktop
- 正确理解left join
热门文章
- 激光SLAM学习--移动机器人技术系列课(智东西)
- 数学学习--最小二乘法案例剖析
- 北斗导航 | GNSS技术在自动驾驶中的作用
- Oracle 11g 安装后续——开发工具篇
- mysql 类型 自动转化_自动MySQL数据类型转换
- mysql 执行计划 优化_执行计划
- 计算机键盘音乐好汉歌,好汉歌 MIDI File Download :: MidiShow
- html iframe 播放视频播放,播放iframe视频点击链接javascript
- 【深度学习】Ivy 开源框架,深度学习大一统时代到来?
- 【深度学习】梯度消失和梯度爆炸问题的最完整解析