美文网首页
41 jvm内存结构分析

41 jvm内存结构分析

作者: 滔滔逐浪 | 来源:发表于2020-08-12 10:14 被阅读0次

    jvm内存区域分配
    java 堆是各线程共享的内存区域,在jvm启动时创建,这块区域是jvm中最大的
    用于存储应用的对象和数组,也是gc的主要回收区,一个jvm实例只存在一个队内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类,方法,常变量放到对内存中,以方便执行器执行。堆内存分为三部分,新生代,老年代,永久代。
    Jdk1.6及之前:常量池分配在永久代 。
    Jdk1.7:有,但已经逐步“去永久代” 。
    Jdk1.8及之后:无永久代,改用元空间代替(java.lang.OutOfMemoryError: PermGen space,这种错误将不会出现在JDK1.8中)。

    jvm内存结构: 堆,栈,方法区,jvm内存结构
    java内存模型: java内存结构 JMM
    栈: 线程栈
    java栈是线程私有的是在线程创建的时候创建,他的生命周期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只有线程一结束就over,生命周期和线程一致。基本类型的变量和对象的引用变量都是在函数的栈内存中分配 。
    每个方法执行的时候都会有一个栈帧栈帧里主要存储3类数据:
    局部变量表: 输入参数和输出参数以及方法内的变量
    栈操作: 记录出栈和入栈的操作
    栈帧数据: 包括类文件,方法等。

    java内存结构;
    堆: 存放new ,数组,堆线程共享
    线程安全问题: JMM主内存

    虚拟机栈(线程栈):栈不共享。每个线程都有自己独立的栈空间,相互之间不影响。JMM本地空间/工作内存/主内存的副本数据。

    本地方法栈: java代码调用c语言代码实现jni
    方法区: 存放: 1,类的信息, 2 常量 ,3 静态变量 4 运行时常量。多个线程共享,存在安全问题:
    程序计数器(pc程序计数器): 记录当前线程行号,在多线程的情况下记录多线程之间上下文切换的位置。
    类加载器: 读取我们的class字节码文件到jvm 虚拟机内存中。

    image.png

    栈:
    栈: 是一种数据结构 先进后出 后进先出
    队列: 先进先出
    虚拟机栈存放:
    1, 局部变量
    2,栈帧 (记录方法的信息)
    3,栈操作。
    栈空间什么时候销毁:1 当我们的方法执行完毕后,栈帧空间会被销毁。
    2,抛出异常栈帧空间会销毁

    package com.taotao.jvm1.day04;
    
    /**
     *@author tom
     *Date  2020/8/12 0012 8:33
     *栈帧空间
     */
    public class Test005 {
    
        public int mk01() {
            //一个方法一个栈帧空间
            return mk02();
        }
    
        private int mk02() {
            int j = 1;
            int z = j + 1;
            return j;
    
        }
    
        /**
         * 3个栈帧
         * @param args
         */
        public static void main(String[] args) {
            Test005 a = new Test005();
            Test005 b = a;
            System.out.println(a.mk01());
            new Thread().start();
        }
    }
    
    
    

    程序计数器:
    1,记录我们当前的线程执行的行号,只有在多线程里才有作用,线程切换的时候通过程序计数器知道在哪继续执行。

    多线程上下文切换的概念:
    将class文件 反汇编:
    javap -c -v class地址

    Javap -c -v F:\works\2020\mayiketang\7\jvm\jvm1\target\classes\com\taotao\jvm1\classloader\Test005.class
    
    

    本地方法栈
    本地方法栈和JVM栈发挥的作用非常相似,也是线程私有的,区别是JVM栈为JVM执行Java方法(也就是字节码)服务,而本地方法栈为JVM使用到的Native方法服务。它的具体做法是在本地方法栈中登记native方法,在执行引擎执行时加载Native Liberies.有的虚拟机(比如Sun Hotpot)直接把两者合二为一。
    也就是 java调用c语言代码 jni技术

    image.png

    栈帧空间包括: 局部变量表 操作数栈 动态链接 方法地址
    栈帧:
    一个方法对应一个栈帧空间。每个方法都有独立的栈帧内存空间,栈数据结构: 先进后出销毁。
    栈帧内部细节结构: 局部变量表,操作数栈,动态链接,方法出口。,栈帧就是每个方法需要执行的运行时内存空间。
    每个运行时需要的内存的叫做虚拟机栈
    每个栈有多个栈帧组成,对应着每次方法调用时占用的内存
    每个线程只能有一个活动的栈。对应着当前执行的方法。
    idea 查看栈帧:


    image.png

    程序计数器:
    记录当期线程执行下一行指令的执行地址,作用主要记录多线程上下文切换过程中记录当前线程的下一指令。
    本地方法栈:
    本地方法栈和jvm栈发挥的作用非常类似,也是线程私有的,区别是jvm栈执行java方法(也就是字节码服务),而本地方法栈为jvm使用到的native方法服务,特的具体做法是本地方法栈中登记native方法。在执行引擎时加载nativeLIberies。也就是java调用c语言代码jni技术
    栈溢出:
    递归调用: 栈溢出
    原因: 在我们占空间中产生了非常多的栈帧空间一直没有释放。

    image.png

    如何避免栈溢出:

    1,增加栈内存
    2,减少递归深度调用。

    package com.taotao.jvm1.day04;
    
    /**
     *@author tom
     *Date  2020/8/12 0012 10:06
     *-Xss256k  java.lang.StackOverflowError 性能调优
     */
    
    public class StackTest {
     private  static  int count;
    
        public static void main(String[] args) {
            mk01();
        }
    
        private static void mk01() {
            count++;
            System.out.println("count:"+count);
            mk01();
        }
    }
    
    
    
    image.png image.png

    堆内存溢出:
    在申请内存的时候,内存不足,产生对内存溢出:

    package com.taotao.jvm1.day04;
    
    import java.util.ArrayList;
    
    /**
     *@author tom
     *Date  2020/8/13 0013 9:36
     *-Xmx8m
     */
    public class HeapTest {
        public static void main(String[] args) {
            int i=0;
            try {
                ArrayList<String> strings=new ArrayList<>();
                while (true){
                    strings.add("mk");
                    i++;
                }
    
    
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    
    
    

    堆内存泄露:
    java.lang.OutOfMemoryError: GC overhead limit exceeded
    这种机制也会有一些问题:就是被占用的内存,经过多次长时间的gc操作都无法回收,导致内存越来越少,俗称内存泄露。jvm就会报java.lang.OutOfMemoryError: GC overhead limit exceeded错误。

    package com.taotao.jvm1.day04;
    
    import java.util.HashMap;
    
    /**
     *@author tom
     *Date  2020/8/13 0013 9:41
     *内存泄露问题
     * -Xmx3M -Xms3M
     */
    public class HashMapMemoryLeak {
    
        public static void main(String[] args) {
            HashMap<HashKey2, Integer> map = new HashMap<HashKey2, Integer>(1000);
            int counter = 0;
    
            while (true) {
                //循环插入新对象new出很多很多内存地址不等的对象
                HashKey2 p = new HashKey2("mk", "22");
                map.put(p, 1);
                counter++;
                if (counter % 1000 == 0) {
                    System.out.println("map size:" + map.size());
                    System.out.println("运行:" + counter + "次后,可用内存剩余" + Runtime.getRuntime().freeMemory() / (1024 * 1024) + "MB");
    
    
                }
            }
        }
    
        static class HashKey2 {
            private final String id;
            private String name;
    
            public HashKey2(String name, String id) {
                this.name = name;
                this.id = id;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            @Override
            public int hashCode() {
                return id.hashCode();
            }
    
            /**
             * hashMap 不管怎么new 多少次 只会key 只会引入一次 不会继续添加。
             *
             * @param obj
             * @return
             */
            @Override
            public boolean equals(Object obj) {
                if (obj instanceof HashKey2)
                    return name.equals(((HashKey2) obj).name) && id.equals(((HashKey2) obj).id);
                else
                    return false;
            }
        }
    }
    
    
    

    堆内存诊断工具

    A. Jps工具 - 查看当前系统有那些java进程
    1.Jps
    2.jmap -heap 进程id
    Jmp工具 查看堆内存占用情况

    B.Jconsole工具 图形界面管理 线程、cpu 堆内存
    E:\java8\jdk\bin\jconsole.exe

    相关文章

      网友评论

          本文标题:41 jvm内存结构分析

          本文链接:https://www.haomeiwen.com/subject/lltpdktx.html