JVM学习(学习中,同步更新)

作者: 秋波未央 | 来源:发表于2019-12-11 21:45 被阅读0次

    1.什么是JVM?

    定义:Java Virtual Machine-java 程序的运行环境(二进制字节码的运行环境)

    优点:1.一次编码,到处运行。

    2.自动内存管理,垃圾回收功能。

    3.数组下标越界越界检查

    4.多态

    比较:

    JVM学习(学习中,同步更新)

    作用:1.面试2.理解底层的实现原理(长远发展必过)3.中高级程序员必备技能。

    学习路线

    JVM学习(学习中,同步更新)

    一.内存结构

    1.程序计数器(寄存器)

    Program Counter Register

    运行过程:

    二进制编码—>解释器—>机器码—>CPU

    作用:记住下一条jvm指令的执行地址,如果没有它将不知道执行哪条指令

    特点:1.是线程私有的2.不会存在内存溢出

    二.虚拟机栈(线程运行时需要的内存空间)

    JVM学习(学习中,同步更新)

    栈帧:一个栈帧对应一个方法的调用,是每个方法运行时需要的内存

    注意:每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法。

    问题辨析:

    1.垃圾回收是否涉及栈内存?

    答:不涉及。

    2.栈内存分配越大越好么?

    答:栈内存越大,可运行的线程数越少,所以并不是越大越好。

    3.方法内的局部变量是否线程安全?

    答:局部变量是线程私有的,不会受到其它线程的干扰。

    扩展:若为 static int x=0.多线程共享这个数,不加操作就会产生混乱,要考虑线程安全性。

    总结:线程是否安全,要看变量是否共享,是否逃离了方法的作用范围(例:有return返回值的方法)

    栈内存溢出:

    1.栈帧过多导致的(一般)

    2.栈帧过大导致

    运行错误:java.lang.StackOverflowError.

    线程运行诊断:

    案例1:cpu占用过多

    解决方式:定位到占用线程过高的那个线程,结束进程。

    案例2:程序运行长时间没结束

    解决方式:造成原因是两个线程产生了死锁,释放线程的锁就解决了。

    3.本地方法栈:给本地方法提供一个运行的空间

    三.堆

    定义:通过关键字new创建的对象都会使用堆内存

    特点:

    1.它是线程共享的,堆中对象都需要考虑线程安全的问题。

    2.有垃圾回收机制。

    堆内存的溢出:

    报错代码:java.lang.OutofMemoryError:Java heap space

    对堆空间设置参数:-Xmx_m(_上填要设置的值)

    注:堆空间可以设置小一点,这样可以尽快解决关于堆内存产生的问题。

    堆内存诊断:

    1.jps工具

    查看当前系统中有哪些java进程

    2.jmap工具

    查看堆内存占用情况。heap 进程id

    3.Jconsole工具

    图形界面的,多功能的检测工具,可以连续监测。

    案例:垃圾回收后内存任然占用很高

    分析:对象一直被引用,未能回收。


    四.方法区

    定义:是所有java虚拟机线程共享的区,它存储了与类相关的一些信息(成员变量、方法数据、成员方法、构造器的方法、类的构造器)

    注解:方法区是在虚拟机启动时被创建,逻辑上是堆的一个组成部分,但要注意的是不同厂商制作的都有些许差异。

    方法区图解:

                        JVM内存结构1.6图解

    JVM学习(学习中,同步更新)

    由图可知:在1.6中,方法区的实现叫永久代,String Table叫字符串表(俗称:串池)

                  JVM内存结构1.8图解

    JVM学习(学习中,同步更新)

    对比:在1.8中,方法区的实现变成了MetaSpace,将不再占用堆内存了,换句话说它已经不是由JVM管理它的内存结构了,它已经被移动到本地内存(操作系统内存)当中,同时StringTable被移到了Heap中。

    方法区内存溢出

    类加载器的作用:加载类的二进制字节码。

    1. 内存结构1.8以前会导致永久代内存溢出

    永久代内存溢出报错:

    Java.lang.OutofMemoryError:PermGen space

    2. 内存结构1.8之后会导致元空间内存溢出

    元空间内存溢出报错:

    Java.lang.OutofMemoryError:Metaspace

    实际场景内存溢出辨析:

    当一些项目用到Spring框架和mybatis框架时,经常会产生大量的在运行期间生成的类。(在1.8以前常出现)

    常量池作用:给指令提供一些常量符号,根据常量符号去找到对应的类名、方法名、参数类型、字面量等信息。

    补充:二进制字节码(类的基本信息、常量池、类方法定义、包含了虚拟机指令)

    运行时常量池,常量池是*.Class文件中的,当该类被加载时它的常量池信息就会放入运行时的常量,并把里面的符号地址变为真实地址。


    五.StringTable特性

    1.常量池中的字符串仅是符号,第一次用到时才变为对象

    2.利用串池的机制,来避免重复创建字符串对象

    3.字符串常量拼接的原理是编译期优化

    注:拼接的仅存在于堆中,串池中没有

    4.字符串常量拼接的原理StringBuilder(1.8)

    5.可以使用intern主动将串池中还没有的字符串对象放入串池

    例:

    String s=newString("a")+newString("b");

    //new String("ab")

    String s2=s.intern();

    //将这个字符串对象尝试放入串池,如果有则不会放入,如果没有则放入串池,会把串池中的对象返回。

    System.out.println(s2=="ab");

    //运行结果为true,因为“ab”这个对象在之前已经被放入串池中了,因此不会创建新的对象,所以s2的对象就是“ab”

    System.out.println(s=="ab");

    //运行结果为true,因为intern将s的对象“ab”放入了串池中,并把“ab”返回给了s,所以s的对象就是“ab”

    相关文章

      网友评论

        本文标题:JVM学习(学习中,同步更新)

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