「慕ke体系」Java工程师2023升级/2024

115 阅读5分钟

Java工程师 2024

核心代码,注释必读

// download:3w ukoou com

Java 运行时环境

Java 程序是首个使用 Java 虚拟机(JVM)结合以上两种方法的语言。Java 代码编译器称为 Java 虚拟机。任何 Java 文件都将首先编译成字节代码。Java 字节代码仅可在 JVM 中运行。然后,JVM 将解释字节代码,然后在基础硬件平台中运行它。因此,如果应用程序在 Windows 机器中运行,则 JVM 会将其解释为可在 Windows 上运行。但是,如果应用程序在 Linux 等开源平台中运行,则 JVM 会将其解释为可在 Linux 上运行。

慕课Java工程师2023 - java JVM运行机制和原理

运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件),JVM才能识别并运行它,JVM针对每个操作系统开发其对应的解释器,所以只要其操作系统有对应版本的JVM,那么这份Java编译后的代码就能够运行起来,这就是Java能一次编译,到处运行的原因。

JVM运行字节码:字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。

利用Java API编写的应用程序(application) 和小程序(Java applet) 可以在任何Java平台上运行而无需考虑底层平台, 就是因为有Java虚拟机(JVM)屏蔽了与具体操作系统平台相关的信息,实现了程序与操作系统的分离,从而实现了Java 的平台无关性,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。

1.JVM概念

JVM即 Java Virtual Machine ,Java虚拟机。它是由软件技术模拟出计算机运行的一个虚拟的计算机。

Java虚拟机主要由字节码指令集、寄存器、栈、垃圾回收堆和存储方法域等构成。

2.JVM周期:

JVM在Java程序开始执行的时候,它才运行,程序结束的时它就停止。

一个Java程序会开启一个JVM进程,如果一台机器上运行三个程序,那么就会有三个运行中的JVM进程。

JVM中的线程分为两种:守护线程和普通线程

守护线程是JVM自己使用的线程,比如垃圾回收(GC)就是一个守护线程。

普通线程一般是Java程序的线程,只要JVM中有普通线程在执行,那么JVM就不会停止。

权限足够的话,可以调用exit()方法终止程序。

3.JVM的结构体系:

·每个JVM都有两种机制:

①类装载子系统:装载具有适合名称的类或接口

类装载子系统也可以称之为类加载器,JVM默认提供三个类加载器:

1、BootStrap ClassLoader :称之为启动类加载器,是最顶层的类加载器,负责加载JDK中的核心类库,如 rt.jar、resources.jar、charsets.jar等。

2、Extension ClassLoader:称之为扩展类加载器,负责加载Java的扩展类库,默认加载$JAVA_HOME中jre/lib/*.jar 或 -Djava.ext.dirs指定目录下的jar包。

3、App ClassLoader:称之为系统类加载器,负责加载应用程序classpath目录下所有jar和class文件。

除了Java默认提供的三个ClassLoader(加载器)之外,我们还可以根据自身需要自定义ClassLoader,自定义ClassLoader必须继承java.lang.ClassLoader 类。除了BootStrap ClassLoader 之外的另外两个默认加载器都是继承自java.lang.ClassLoader 。BootStrap ClassLoader 不是一个普通的Java类,它底层由C++编写,已嵌入到了JVM的内核当中,当JVM启动后,BootStrap ClassLoader 也随之启动,负责加载完核心类库后,并构造Extension ClassLoader 和App ClassLoader 类加载器。

类加载器子系统不仅仅负责定位并加载类文件,它还严格按照以下步骤做了很多事情:

1、加载:寻找并导入Class文件的二进制信息
2、连接:进行验证、准备和解析
     1)验证:确保导入类型的正确性
     2)准备:为类型分配内存并初始化为默认值
     3)解析:将字符引用解析为直接引用
3、初始化:调用Java代码,初始化类变量为指定初始值

②执行引擎:负责执行包含在已装载的类或接口中的指令 。

//例子:
Integer i1 = 20;
Integer i2 = 20;
System.out.println(i1=i2);//输出TRUE

Byte、Short、Integer、Long、Character这5种包装类都默认创建了数值[-128 , 127]的缓存数据。当对这5个类型的数据不在这个区间内的时候,将会去创建新的对象,并且不会将这些新的对象放入常量池中。

//IntegerCache.low = -128
//IntegerCache.high = 127
public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
//例子
Integer i1 = 200;
Integer i2 = 200;
System.out.println(i1==i2);//返回FALSE

Float 和Double 没有实现常量池。

String包装类与常量池

String str1 = "aaa";

当以上代码运行时,JVM会到字符串常量池查找 "aaa" 这个字面量对象是否存在?

存在:则返回该对象的引用给变量 str1 。

不存在:则在堆中创建一个相应的对象,将创建的对象的引用存放到常量池中,同时将引用返回给变量 str1 。

String str1 = "aaa";
String str2 = "aaa";
System.out.println(str1 == str2);//返回TRUE

因为变量str1 和str2 都指向同一个对象,所以返回true。

String str3 = new String("aaa");
System.out.println(str1 == str3);//返回FALSE