先来段代码,大家瞧瞧运行pritln的结果是什么?(认真想一想哦?)



package com.java.baseknowledge.classload;

public class ClssTest {
    
    
    public static void main(String[] args) {
        Single sing=Single.getInstance();
        System.out.println(sing.i);
        System.out.println(sing.j);
    }

}

class Single{
    
    public static Single sing =new Single();
    public static int i;    
    public static int j =9;
    
    private Single () {
        i++;
        j++;
    }
    
    public static Single getInstance() {
        
        return sing;
    }
}



---开篇:

1.java virtual machine 与程序的生命周期



1.执行了system.exit()的方法
2.program正常执行结束
3.program 运行过程中遇到了error 和exception
4.由于操作系统错误导致的Java virtual machine 退出



2.关于类的加载,连接与初始化



1,加载(classload):查找并加载类的二进制数据(硬盘到内存)。--》将其放在运行时数据区的方法区内,并在堆内存创建一个创建一个java.lang.class对象。用来封装类在方法区的数据结构,提供了访问方法区内的数据结构的接口即反射;
2,连接:
    (1)验证:确保被加载的类的正确性。
    (2)准备:为类的静态变量分配内存,并将其初始化为默认值。----》初始化默认值是 0 null 之类的,并没有赋予我们所赋予的值
    (3)解析:将类中的符号引用转换为直接引用
3.初始化:为类的静态变量赋于正确的初始值。(这里的赋予正确初始值是用户所赋予的值)



类加载器详解



1.创建类的实例---》 xx x=new xx();
2.访问某个类或者接口的静态变量,或者对静态变量赋值
3.调用类的静态方法
4,反射调用--》 class。forname();
5.初始化一个类的子类
6.java virtual machine start 标明为启动类的类



classloader 源码:
  A class loader is an object that is responsible for loading classes. The
 * class <tt>ClassLoader</tt> is an abstract class.  Given the <a
 * href="#name">binary name</a> of a class, a class loader should attempt to
 * locate or generate data that constitutes a definition for the class.  A
 * typical strategy is to transform the name into a file name and then read a
 * "class file" of that name from a file system.
 *
 * <p> Every {@link Class <tt>Class</tt>} object contains a {@link
 * Class#getClassLoader() reference} to the <tt>ClassLoader</tt> that defined
 * it.
 *
Trnslation:
class loader 是一个负责加载类的一个对象,是一个抽象的类,类加载器应该尝试定位或生成构成类的定义的数据
一种典型的策略是将名称转换成文件名,然后从文件系统中读取该名称的“类文件”。

每一个class 对象都包含了一个getclassloader 的方法引用,用于定义它的classloader

然后我们看一看class 类中的getclassloader method define;

/**

     * Returns the class loader for the class.  Some implementations may use

     * null to represent the bootstrap class loader. This method will return

     * null in such implementations if this class was loaded by the bootstrap

     * class loader.

     *

     * <p> If a security manager is present, and the caller's class loader is

     * not null and the caller's class loader is not the same as or an ancestor of

     * the class loader for the class whose class loader is requested, then

     * this method calls the security manager's {@code checkPermission}

     * method with a {@code RuntimePermission("getClassLoader")}

     * permission to ensure it's ok to access the class loader for the class.

     *

     * <p>If this object

     * represents a primitive type or void, null is returned.

Translation:

  返回这个类的类加载器,一些实现类可能会返回空去代表类加载器是bootstrap 类加载器。
如果类是被bootstrap 类加载的,就会返回空。
  原始的数据类型的加载器都会返回空;



三种 classloader



1.根类加载器(bootstrap 使用c++编写,无法看到底层实现)
2.扩展类加载器
3.系统加载器



连接的过程:



验证:

  对类文件的检查,确保类文件遵循Java 类文件固定格式
  语义检查,死否遵循语法规范
  字节码验证
  二进制兼容验证



准备
  为类的静态变量赋于初始值,并不是我们赋予的值,



解析:
    符号引用转换为直接引用,即比如car类的 run() 方法的符号引用是由run 方法的全名和相关描述符组成,在解析是,Java 会把这个符号引用替换为一个指针,指针指向
方法内存位置,指针就是直接引用;



初始化过程:



为静态变量赋于我们所给予的值,代替类连接过程准备阶段赋予的初始值,没有则保持初始值
静态变量的声明语句与静态代码块都是类初始化的语句,只是谁前谁后的问题



如上面例子中的--



package com.java.baseknowledge.classload;

public class ClssTest {
    
    
    public static void main(String[] args) {
        Single sing=Single.getInstance();
        System.out.println(sing.i);
        System.out.println(sing.j);
    }

}

class Single{
    /**
  * =======连接阶段赋初始值======
  *      sing =null;
  *      i=0;
  *      j=0;
  *==========初始化阶段===========
  *    new singal ==》 i=1;j=10;
  *    i =1;
  *    j=9;
  **/  
    public static Single sing =new Single();
    public static int i;    
    public static int j =9;
    
    private Single () {
        i++;
        j++;
    }
    
    public static Single getInstance() {
        
        return sing;
    }
}