java 基础学习之JVM学习

JVM学习

JVM学习


  • [参考]: https://blog.csdn.net/xiangzhihong8/article/details/80412795 “比较详细”

  • [参考2]: https://blog.csdn.net/u011546655/article/details/52175550

  • 概念

    • 又称为JVM.
    • 通过在实际的计算机上仿真模拟各种计算机功能的虚拟计算机。
    • 主要由字节码指令集,寄存器,栈,垃圾回收堆和存储方法域构成。
    • java 程序 与操作系统之间的翻译官
      • Java 程序编译后 生成.class文件. JVM针对不同的都有不同的解释器,所以只要针对系统中有相关的jvm,那么对应的编译后的程序就可以运行起来. — 一份代码多次运行.
  • JVM 生命周期

    • JVM 随Java程序开始而开始,结束而停止。一个Java程序会开启一个JVM进程,一台计算机上可以运行多个程序===> 多个JVM进程
    • JVM将线程分为:守护线程和普通线程两种。
      • 守护线程:
        • JVM自己使用的线程,比如GC(垃圾回收)
      • 普通线程一般是Java程序的线程,只要JVM有普通线程在执行,JVM就不会停止.
  • JVM 内存模型

    • 堆和方法区是所有线程共有的,虚拟机栈和本地方法栈和程序计数器都是线程私有的。
    • 堆内存(线程共享)
      • 分为年轻代和老年代. 还有一个永久代在1.8之前存在,1.8(含)之后永久代被移除。
      • 堆内存是内存优化中的一个重要内容。
    • 方法区(线程共享)
      • 存储已经被虚拟机加载的类信息,常量,静态变量,即时编译(JIT)后的代码等数据。
      • 因为线程共享,所以方法区的信息,必须要保证线程安全。如果有两个线程同时加载一个类,只能一次加载一个。
      • 运行时,方法区内存可变更(扩展以及回收)。方法区里面的对象也可以被回收,但必须是该类没有任何引用的情况,才可以被回收。
    • 程序计数器
      • 职责: 字节码解释器依赖程序计数器来选取下一条要执行的指令。分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。
      • JVM多线程依赖线程轮流切换并分配处理器执行时间的方式来实现的,为了每个线程切换后都能够找到正确的下一条指令,所以每个线程都有一个独立的程序计数器
    • Java虚拟机栈
      • 即通常所说的堆栈里面的栈,用于Java方法运行时候的内存模型。
      • Java虚拟栈运行过程:每个方法执行的时候都会创建一个栈帧(stack Frame)用于存储变量表(强类型,所以内存大小不会更改),操作,动态链接,方法出口等信息。每个方法从调用到出栈 的过程,就对用栈帧在虚拟机中从入栈到出栈的过程。
    • 本地方法栈
      • Native Method
        • java调用非java代码的接口。(本质上还是)
      • 主要用于存储本地方法的局部变量表,本地方法的操作数栈等信息,超过作用域时,被自动释放掉
      • 主要用于JVM调用本地方法接口(Native)。
    • 类加载过程
      • Load
        • 一,通过类的全限定名(java.package.class) 获取定义好的二进制字节流(这个应该是编译好的.class文件)
        • 二,将字节流代表的静态存储结构转化为方法区的运行时的数据结构
        • 三,在Java堆生成一个代表该类的java.lang.class对象,作为对方法区中这些数据的访问入口
        • 注意:
          • Load阶段是获取类的二进制类字节流的最佳阶段,开发既可以使用System类加载器,又可以使用自己的类加载器
      • Link 将Java中的二进制代码合并到JVM运行状态之中的过程
        • 一, 验证: 确保被加载类正确
          • 文件格式验证
            • 验证字节流中是否符合class文件的规范。例如是否以OxCAFEBABE开头,主次版本号是否在当前虚拟机的处理范围之内,常量池中常量是否有不被包含支持的类型
          • 元数据验证:对字节码描述的信息进行语义分析。保证其描述的信息与Java语言规范符合.
          • 字节码验证:通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的。
          • 符号引用验证:确保解析动作能正确执行。
          • 注意:验证很重要,但不是必须,对程序运行期没影响。由-Xverifynone参数。
        • 二,准备:为类的静态变量分配内存,并将其初始化为初始值
          • 这个时候分配内存仅是类变量(static),不是实例变量,实例变量会再对象实例化随对象一块分配在Java堆中.
          • 这里的初始值为数据类型的零值(0, 0L, false, null等)
        • 三,解析: 将类中相关符号引用转换为直接引用
      • Initialize 为类的静态变量设置正确的初始值
    • class加载器
      • Bootstap classLoader
        • 负责加载$JAVA_HOME中 jre/lib/rt.jar 里所有的class或Xbootclassoath选项指定的jar包。由C++实现,不是ClassLoader子类。
      • Extension ClassLoader
        • 负责加载java平台中扩展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar 或 -Djava.ext.dirs指定目录下的jar包。
      • App classLoader
        • 负责加载classpath中指定的jar包及 Djava.class.path 所指定目录下的类和jar包
      • Customer classLoader
        • 通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader。