• jvm学习笔记


    1. Java解析

    动态分派

    源码:

    public class DynamicDispatch {

    public static class Human {
    void sayHello() {
    System.out.println("human say hello!");
    }
    }

    static class Man extends Human {
    @Override
    void sayHello() {
    System.out.println("man say hello!");
    }
    }

    static class Woman extends Human {
    @Override
    void sayHello() {
    System.out.println("human say hello!");
    }
    }

    public static void main(String[] args) {
    Human human = new Human();
    Human man = new Man();
    Human woman = new Woman();

    human.sayHello();
    man.sayHello();
    woman.sayHello();
    }

    }

    分析:

    通过javap -v DynamicDispatch.class 获取编译后的二进制文件:

    总结:

    不是根据静态类型来确定,而是在运行时根据实际类型来决定函数的版本。

    静态分派

    源码:

    public class StaticDispatch {

    static class Human {
    }

    static class Man extends Human {
    }

    static class Woman extends Human {
    }

    void sayHello(Human human) {
    System.out.println("human say hello!");
    }

    void sayHello(Man man) {
    System.out.println("man say hello!");
    }

    void sayHello(Woman woman) {
    System.out.println("woman say hello!");
    }

    public static void main(String[] args) {
    StaticDispatch staticDispatch = new StaticDispatch();
    Human human = new Human();
    Human man = new Man();
    Human woman = new Woman();
    staticDispatch.sayHello(human);
    staticDispatch.sayHello(man);
    staticDispatch.sayHello(woman);
    }

    }

    分析:

    通过javap -v StaticDispatch.class 获取编译后的二进制文件:

     通过这段编译,上述的三个方法都初始化了,但是最后再调用的都是human的sayHello方法。

    总结:由于静态分派是在类编译的时候确定类的属性。

    编译器在重载时是通过参数的静态类型而不是实际类型作为判定依据的。并且静态类型是编译期可知的,因此,在编译阶段,Javac编译器会根据参数的静态类型决定使用哪个重载版本。

     

     

    Java语言是一门静态多分派、 动态单分派的语言。

     

    类的初始化

    • <clinit> 类的初始化。静态变量,静态块的初始化。所有的类变量初始化语句和类型的静态初始化器。

    Java在编译之后会在字节码文件中生成<clinit>方法,称之为类构造器,类构造器同实例构造器一样,也会对静态语句块,静态变量进行初始化

    • <init> 对象的初始化

    Java在编译之后会在字节码文件中生成<init>方法,称之为实例构造器。该实例构造器会对语句块,变量进行初始化,并调用父类的构造器。

     

    <clinit>方法是在类加载过程中执行的,而<init>是在对象实例化执行的,所以<clinit>一定比<init>先执行。所以整个顺序就是:

    • 父类静态变量初始化

    • 父类静态语句块

    • 子类静态变量初始化

    • 子类静态语句块

    • 父类变量初始化

    • 父类语句块

    • 父类构造函数

    • 子类变量初始化

    • 子类语句块

    • 子类构造函数

    JDK1.8 默认的垃圾回收器是Parallel Scavenge 和Parallel Old。

    JDK1.9默认的是G1

    开启参数:

    -XX:+Use<垃圾回收器的名称>GC

     

  • 相关阅读:
    hdu多校4
    hdu多校第三场
    牛客多校4
    bzoj 1477 扩展欧几里德
    bzoj 1485 卡特兰数 + 分解因子
    hdu多校 2
    牛客网暑期多校2
    bzoj 1040 基向内环树dp
    hdu 多校第一场
    SPOJ
  • 原文地址:https://www.cnblogs.com/baoyi/p/jvm.html
Copyright © 2020-2023  润新知