1、Java内存模型

  • JMM即Java Memory Model,它定义了主存(即JVM中的方法区和堆区)、工作内存(即JVM中的虚拟机栈)抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。
    • JMM体现在以下几个方面:
      • 原子性-保证指令不会受到线程上下文切换的影响。
      • 可见性-保证指令不会受cpu缓存的影响。
      • 有序性-保证指令不会受cpu指令并行优化的影响。
        Read more »

1、成员变量和局部变量

  • 成员变量和静态变量的线程安全性
    • 如果它们没有共享,则线程安全。
    • 如果它们被共享了,根据它们的状态是否能够改变,又分两种情况。
      • 如果只有读操作,则线程安全。
      • 如果有读写操作,则这段代码是临界区,需要考虑线程安全。
  • 局部变量的线程安全性
    • 局部变量是线程安全的。
    • 但局部变量引用的对象则未必。
      • 如果该对象没有逃离方法的作用访问,它是线程安全的。
      • 如果该对象逃离方法的作用范围,需要考虑线程安全。
        Read more »

1、守护线程

  • 默认情况下,Java进程需要等待所有线程都运行结束,才会结束。有一种特殊的线程叫做守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @Slf4j
    public class TestThread {
    public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
    while (true) {
    if (Thread.currentThread().isInterrupted()) {
    break;
    }
    }
    log.debug("结束");
    }, "t1");
    // 设置该线程为守护线程
    t1.setDaemon(true);
    t1.start();

    Thread.sleep(1000);
    log.debug("结束");
    }
    }
Read more »

1、进程和线程

进程

  • 程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至CPU,数据加载至内存。在 指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理IO的。
  • 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程。
  • 进程就可以视为程序的一个实例。大部分程序可以同时运行多个实例进程(例如记事本、画图、浏览器 等),也有的程序只能启动一个实例进程(例如网易云音乐、360安全卫士等)。
Read more »

1、概述

  • 类加载器是JVM执行类加载机制的前提。

  • ClassLoader的作用:

    • ClassLoader是Java的核心组件,所有的Class都是由ClassLoader进行加载的,ClassLoader负责通过各种方式将Class信息的二进制数据流读入JVM内部,转换为一个与目标类对应的java.lang.Class对象实例。然后交给Java虚拟机进行链接、初始化等操作。因此,ClassLoader在整个装载阶段,只能影响到类的加载,而无法通过ClassLoader去改变类的链接和初始化行为。至于它是否可以运行,则由Execution Engine决定。
Read more »

1、概述

  • 在Java中数据类型分为基本数据类型和引用数据类型。基本数据类型由虚拟机预先定义,引用数据类型则需要进行类的加载。

  • 按照Java虚拟机规范,从class文件到加载到内存中的类,到类卸载出内存为止,它的整个生命周期包括如下7个阶段。

Read more »

1、概述

  • Java字节码对于虚拟机,就好像汇编语言对于计算机,属于基本执行指令。
  • Java虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码,Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数,Operands)而构成。由于Java虚拟机采用面向操作数栈而不是寄存器的结构,所以大多数的指令都不包含操作数,只有一个操作码。
  • 由于限制了Java虚拟机操作码的长度为一个字节(即0~255),这意味着指令集的操作码总数不可能超过256条。官方文档:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html
  • 熟悉虚拟机的指令对于动态字节码生成、反编译Class文件、Class文件修补都有着非常重要的价值。因此,阅读字节码作为了解Java虚拟机的基础技能,需要熟练掌握常见指令。
    Read more »

1、解析字节码文件作用

  • 通过反编译生成的字节码文件,我们可以深入的了解java代码的工作机制。但是,自己分析类文件结构太麻烦了!除了使用第三方的jclasslib工具之外,oracle官方也提供了工具:javap。

  • javap是jdk自带的反解析工具。它的作用就是根据c1ass字节码文件,反解析出当前类对应的code区(字节码指令)、局部变量表、异常表和代码行偏移量映射表、常量池等信息。

  • 通过局部变量表,我们可以查看局部变量的作用域范围、所在槽位等信息,甚至可以看到槽位复用等信息。

    Read more »

一、概述

1.1 字节码文件的跨平台性

  • Java语言:跨平台的语言(write once, run anywhere)
    • 当]ava源代码成功编译成字节码后,如果想在不同的平台上面运行,则无须再次编译。
    • 这个优势不再那么吸引人了。 Python、PHP、Perl、Ruby、Lisp等有强大的解释器。
    • 跨平台似乎己经快成为一门语言必选的特性。
  • Java虚拟机:跨语言的平台
    • Java虚拟机不和包括Java在内的任何语言绑定,它只与“Class文件”这种特定的二进制文件格式所关联。无论使用何种语言进行软件开发,只要能将源文件编译为正确的Class文件,那么这种语言就可以在Java虚拟机上执行。可以说,统一而强大的Class文件结构,就是Java虚拟机的基石、桥梁。
    • 所有的JVM全部遵守]ava虚拟机规范,也就是说所有的JVM环境都是一样的,这样一来字节码文件可以在各种JVM上运行。
      Read more »