先来段代码,大家瞧瞧运行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;
}
}