美文网首页
Java JVM & ByteCode

Java JVM & ByteCode

作者: bowen_wu | 来源:发表于2021-09-16 16:37 被阅读0次

    概述

    JVM => Java Virtual Machine
    JLS => Java Language Specification => Java 语音规范 => 定义 Java 语言的语法
    JVMS => Java Virtual Machine Specification => Java 虚拟机规范 => 定义字节码如何在 JVM 中执行

    JLS 与 JVMS 没有任何关系

    JVM 基本结构

    Heap

    • 所有的对象都在堆上分配
    • 只能操纵对象的引用或者地址
    • 只能控制对象的诞生,但是无法控制它的死亡

    方法栈

    • 线程私有
    • 每当一个方法调用发生,方法栈就入栈一个栈帧
    • 每当方法退出(放回或异常),栈帧就被弹出 => 栈帧是对方法每一次调用的一个表示,每一次调用会产生一个新的栈帧
    • 局部变量在栈帧中分配
    • 当栈深度过大时抛出 StackOverflow

    栈帧

    1. 局部变量表 => Local Variable Table
    2. 操作数栈 => Operand Stack
    SourceCode vs ByteCode

    每当方法调用开始的时候,Local Variable Table 会被初始化成当前方法的参数

    Method Area

    • 被整个虚拟机所共享的 Class 信息等 => new Cat() 的时候,Cat类型信息来源于 Method Area => readonly
    • 运行时常量池 => String.intern => 常量池存放,但是每个值都有一个地址,使得每次调用 intern 方法时返回的都是值的地址,多次调用对象是不变的,那个值 & 地址都是不变的
      String s1 = new String("ABCDE");
      String s2 = new String("ABCDE");
      String s3 = s1.intern();
      String s4 = s2.intern();
      
      System.out.println(s1 == s2); // false
      System.out.println(s3 == s4); // true
      
    String intern
    • Java 7 之前:永久代(PermGen) => OutOfMemory: perm gen => 永久代和堆放在一起,会和堆抢占内存,OutOfMemory 经常会发生
    • Java 8 之后:元空间(Metaspace) => 元空间和 Native 共享内存

    Bytecode

    Bytecode == IR => Intermediate Representation
    JVM 实现跨平台基石 => ByteCode

    • 一种基于栈的、与平台无关的计算模型 => 基于栈:所有的计算都是基于栈帧里面的 Operand Stack 执行的
    • 可以由多种方式生成 => JVM 上的编程语言 & 直接生成字节码

    查看 & 阅读

    • javap => javap -v -private x.class => Java 自带的反编译工具,可以用来查看字节码信息
    • classpy
    • 反编译器 => IDEA ASM Bytecode Viewer Plugin

    加载 & 执行

    1. Class Loader => 将 class 文件加载成虚拟机内部的 Class 类的表示
    2. Bytecode Verifier => 验证字节码的合法性
    3. Java Runtime System
    4. Native OS
    类加载器 Class Loader

    Class Loader 打通了代码和数据间的障碍

    • 动态加载代码
    • 动态生成代码
    • 动态替换代码

    使用场景

    • Mock
    • AOP
    • 热部署 | 热替换

    双亲委派加载模型

    Java 8 及之前,Java 9 引入了模块系统
    当任何一个类加载器尝试去加载一个类时都会委托给它的父亲,如果它的父亲可以加载的话,就直接返回,否则就自己尝试去加载,并且成为要加载那个类的类加载器

    TODO:ClassLoad 文档

    1. Application ClassLoader => CLASSPATH => 负责加载 classpath 里面的包 => 启动参数中的 -cp(classpath)
    2. Extension ClassLoader => jre/lib/ext/*.jar => 负责加载 JVM 中程序运行所需要的类
    3. Bootstrap ClassLoader => jre/lib/*.jar rt.jar(runtime) jce.jar 等 => 负责加载 JVM 启动时的相关类
    ClassLoader loadClass
    • 安全性
    • 正确性 => 类加载器也被 instanceof 所检查 => instanceof 不仅检查类名,还检查类加载器 => cat instanceof Cat => 检查类加载器 cat.getClass().classLoaderCat.class.classLoader 是否一致

    JIT Compiler

    JIT => Just In Time
    AOT => Ahead Of Time

    两种执行方式

    1. JIT => 解释执行 => 方便、跨平台 + 慢
    2. AOT => 编译执行 => 麻烦、不灵活、编译后的代码非常臃肿 + 快

    antlr

    显示语法树
    GitHub

    Quick Start

    OS X
    cd /usr/local/lib
    sudo curl -O https://www.antlr.org/download/antlr-4.9.2-complete.jar
    export CLASSPATH=".:/usr/local/lib/antlr-4.9.2-complete.jar:$CLASSPATH"
    alias antlr4='java -jar /usr/local/lib/antlr-4.9.2-complete.jar'
    alias grun='java org.antlr.v4.gui.TestRig'
    # alias grun='java -cp .:antlr-4.9.2-complete.jar org.antlr.v4.gui.TestRig'
    

    知识点

    1. factorial => 阶乘
    2. 在 Java 世界中所有的参数传递都是拷贝,都发生了一个拷贝的过程
    • 基本数据类型 => 拷贝值
    • 引用数据类型 => 拷贝地址
    1. IDEA Plugin => ASM Bytecode Viewer => 将当前代码编译成字节码查看
    2. List of Java bytecode instructions
    3. 对象的地址在栈中何种形式存储?
    • 32 位操作系统 => 对象的地址在栈中32位 => 4byte
    • 64 位操作系统 => 对象的地址在栈中64位 => 8byte
    1. native 关键字 => 该方法没有 Java 代码,是 Java 虚拟机实现的
    2. String 的 equals => 比较两个 String 是否是同一个对象 | 循环比较每个字符
      String equals
    3. Java Magic Number => CAFEBABE
    4. 字节码版本号约定 => Java 虚拟机只能加载低于或等于该版本的字节码 => 加载高于 Java 虚拟机版本的字节码将会报错 => java.lang.UnsupportedClassVersionError: xxx: Unsupported major.minor version
    5. Java 模式
      • mixed mode => 混合模式
      • interpreter mode => 解释器模式
      • compiled mode => 编译模式

    疑问

    1. 常量池只与 String 有关吗?

    相关文章

      网友评论

          本文标题:Java JVM & ByteCode

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