先来段代码,大家瞧瞧运行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.初始化:为类的静态变量赋于正确的初始值。(这里的赋予正确初始值是用户所赋予的值)
类加载器详解 .java program 对类的主动使用方式,会导致类的初始化,其他方式都不会进行类的初始化。
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; } }