类加载解释
在Java代码中,类型得加载,连接与初始化得过程都是在程序运行期间完成得。提供了更大得灵活性,增加了更多得可能。
类的加载指的时将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法去内,然后在内存中创建一个java.lang.Class对象(规范并未说明Class对象位于哪里,HotSpot虚拟机将其放在了方法区中)用来封装类在方法区内的数据结构。
加载类.class文件的方式
- 从本地系统中直接加载
- 通过网络下载.class文件
- 从zip,jar等归档文件中加载.class文件
- 从专有数据库中提取.class文件
- 将Java源文件动态编译未.class文件
java虚拟机与程序得生命周期
在如下集中情况下,java虚拟机将结束生命周期
- 执行了System.exit()方法
- 程序正常执行结束
- 程序在执行过程中遇到了异常或错误而异常终止
- 由于操作系统出现错误而导致Java虚拟机进程终止
类得加载,连接与初始化
加载:查找并加载类得二进制数据
连接:
- 验证:确保被加载得类的正确性
- 准备:为类的静态变量分配内存,并将其初始化为默认值
- 解析:把类中的符号引用转换为直接引用
初始化:为类的静态变量赋予正确的初始值。
java程序对类的使用方式可分为两种 - 主动使用
- 被动使用
所有的Java虚拟机实现必须在每个类或接口被Java程序==“首次主动使用时”==才能初始化他们。
主动使用的情况有(七种)
- 创建类的实例 new Person();
- 放问某个类或接口的静态变量,或者对该静态变量赋值。
- 调用类的静态方法
- 反射(如Class.forName(“com.lang.String”)
- 初始化一个类的子类
- java虚拟机启动时被标名为启动类的类main
- JDK1.7开始提供的动态语言支持
public class ClassLoaderTest {
public static void main(String[] args) {
System.out.println(Teacher.name);
}
}
class Person{
public static String str="hallo world";
static {
System.out.println("Person Static block");
}
}
class Teacher extends Person{
//当我们将静态属性加上final之后 其他类方法调用该属性时
// 本质上并没有引用到定义常量得类 不会使得本类以父类进行初始化
//为什么?因为被final修饰的字段被视为常量是不可以变得
// 在编译阶段这个常量就会被存入到调用这个常量得所在得方法所在得类得常量池中
public static final String name="jiea";
static {
System.out.println("Teacher Static block");
}
}
对于静态字段来说,只有直接定义了该字段的类才会初始化
子类调用父类的静态字段 父类会进行初始化 而子类不会因为没有用到子类任何静态属性。
在Teacher类中继承了Person类,如果在ClassLoaderTest的主方法中调用**System.out.println(Teacher.str);即调用了父类的静态变量 则会触发对父类的初始化而子类不会。
如果System.out.println(Teacher.name);**这个方法调用子类的静态字段的话,父类也会进行初始化,和创建对象一样会先调用父类的构造的方法再进行子类的初始化