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