Java堆,方法区,Java栈和本地方法栈浅析
来源:互联网 发布:亨德尔 水上音乐 知乎 编辑:程序博客网 时间:2024/05/22 02:14
最近在看《深入理解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());
- }
- }
- }
加上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();
- }
- }
- }
加上永久带的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());
- }
- }
- }
同样加上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;
- }
- }
- }
设置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;
- }
- }
- }
报出异常:Exception in thread "main" java.lang.OutOfMemoryError:unable to create new native thread
不过在windows上运行这个例子要小心,会出现系统假死的情况,有可能需要重启机器才行。
以上几个例子虽然比较简单,但能很好帮助普通的程序员更加直观的了解Java堆,方法区,Java栈和本地方法栈。
- Java堆,方法区,Java栈和本地方法栈浅析
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 从几个sample来学习Java堆,方法区,Java栈和本地方法栈
- 学习Java堆,方法区,Java栈和本地方法栈
- Java栈,PC寄存器,本地方法栈,堆,方法区和运行常量池
- Java中的栈、堆和方法区
- Java 堆、栈和方法区
- 方法区、Java堆、Java栈、本地方法栈、指令计数器及其他隐含寄存器
- java-内存管理(程序计数器、虚拟机栈、本地方法栈、堆、方法区)和常量池
- Java 堆、栈、方法区
- Java中栈内存、堆内存、方法区——浅析
- 正则表达式
- Android 实现监听开机启动开启后台服务,并实现自动重启。
- POJ 2367 拓扑排序
- 第十四周项目1-3:统计字符个数
- 机器学习算法中如何选取超参数:学习速率、正则项系数、minibatch size
- Java堆,方法区,Java栈和本地方法栈浅析
- 一道题目理解js中变量在作用域链与原型链中的查找顺序
- hihocode 第五十周 欧拉路·二
- watch-3D.app开发经验(1)
- android 软键盘在全屏下设置adjustResize无效的问题
- iBokan_ios80_自学系列_1(~循环结构~)
- jQuery开发之DOM操作五
- vim环境搭建,安装插件
- response.getWriter().write()与out.print()的区别