[深入理解Java虚拟机]读书笔记(1):Java内存区域与内存溢出

 2019-12-22 11:03  阅读(1034)
文章分类:JVM

2019120001519\_1.png

1. 方法区:由类装载子系统查找并加载类到内存时,会提取类信息、常量、静态变量放入方法区中。虽然虚拟机规范把方法区描述为堆的一个逻辑部分,但它有个别名叫Non-Heap(非堆)。在HotSpot虚拟机中,方法区也被叫做”永久代”(Permanent Generation),可用**-XX:PermSize=10M -XX:MaxPermSize=10M**来设置其大小(因为有限制,更容易出现内存溢出问题,所以HotSpot官方也有放弃永久代的规划了)。J9、JRockit则是使用进程可用内存的上限。

2.Java堆:堆是被所有线程共享的一块区域,在虚拟机启动时创建,所有对象的实例以及数组都在这里分配内存,JVM会根据new指令在堆中开辟一个确定类型的对象内存空间。堆也是垃圾收集器(GC)管理的主要区域,还可以细分为:新生代和老年代。可用**–Xms20M -Xmx30M**来设置堆的最小值(JVM启动时的值)和最大值。

**3.程序计数器:**程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。每一个线程都有一个程序计数器,当线程执行Java程序时,程序计数器的内容总是下一条将被执行的指令的地址。

4.Java虚拟机栈:与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。可用-Xss10M来设置栈大小

**5.本地方法栈:**本地方法栈与虚拟机栈所发挥的作用非常相似,区别不过是虚拟机栈为JVM执行Java方法服务,而本地方法栈则为JVM使用到的本地方法服务。

方法区内存溢出:

/**
     * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
     * 
     * @author zzm
     */
    public class RuntimeConstantPoolOOM {

        public static void main(String[] args) {
            // 使用List保持着常量池引用,避免Full GC回收常量池行为
            List<String> list = new ArrayList<String>();
            // 10MB的PermSize在integer范围内足够产生OOM了
            int i = 0;
            while (true) {
                list.add(String.valueOf(i++).intern());
            }
        }
    }

堆内存溢出:

/**
     * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
     * 
     * @author zzm
     */
    public class HeapOOM {

        static class OOMObject {
        }

        public static void main(String[] args) {
            List<OOMObject> list = new ArrayList<OOMObject>();

            while (true) {
                list.add(new OOMObject());
            }
        }
    }

栈内存溢出:

/**
     * VM Args:-Xss2M
     * 
     * @author zzm
     */
    public class JavaVMStackOOM {
        private void dontStop() {
            while (true) {
            }
        }

        public void stackLeakByThread() {
            while (true) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        dontStop();
                    }
                });
                thread.start();
            }
        }

        public static void main(String[] args) throws Throwable {
            JavaVMStackOOM oom = new JavaVMStackOOM();
            oom.stackLeakByThread();
        }
    }
点赞(1)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> [深入理解Java虚拟机]读书笔记(1):Java内存区域与内存溢出

相关推荐