Java核心技术一-Java基础
一. Java平台
你对 Java 最直观的印象是什么呢?是它宣传的 “Write once, run anywhere”,还是目前看已经有些过于形式主义的语法呢?
Java本身是一种面向对象语言,有两个显著方面:
一是所谓的"书写一次,到处运行"(Write once, run anywhere),能够非常容易地获得跨平台能力
另外就是垃圾收集 (GC, Garbage Collection),Java通过垃圾收集器 回收分配内存, 大部分情况下, 程序员不需要操心内存的分配和回收.
我们日常会接触到 JRE(Java Runtime Environment)或者 JDK(Java Development Kit)
JRE,也就是 Java 运行环境,包含了 JVM 和 Java 类库, 以及一些模块等。
JDK 可以看作是 JRE 的一个超集,提供了更多工具,比如编译器、各种诊断工具等。
对于"Java是解释执行"这句话说法不太准确.
我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码(bytecode),
然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。
但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,
都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,
这种情况下部分热点代码就属于编译执行,而不是解释执行了。
JVM类的加载过程
加载 > 验证 > 准备 > 解析 > 初始化 > 使用 > 卸载
7个步骤 (验证,准备,解析 -> 连接Linking)
加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序进行,
而解析阶段则不一定,它在某些情况下可能在初始化阶段后在开始,因为java支持运行时绑定。
类的加载时机
加载(loading)阶段,java虚拟机规范中没有进行约束,但初始化阶段,java虚拟机严格规定了有且只有如下5种情况必须立即进行初始化(初始化前,必须经过加载、验证、准备阶段):
(1)使用new实例化对象时,读取和设置类的静态变量、静态非字面值常量(静态字面值常量除外)时,调用静态方法时。
(2)对内进行反射调用时
(3)当初始化一个类时,如果父类没有进行初始化,需要先初始化父类。
(4)启动程序所使用的main方法所在类
(5)当使用1.7的动态语音支持时。
如上5种场景又被称为主动引用,除此之外的引用称为被动引用,被动引用有如下3种常见情况
(1)通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
(2)定义对象数组和集合,不会触发该类的初始化
(3)类A引用类B的static final常量不会导致类B初始化(注意静态常量必须是字面值常量,否则还是会触发B的初始化)