

使用new关键字实例化对象时、设置或读取一个类的静态字段(final 修饰的静态字段除外,final修饰的常量会在编译期放入常量池中)时和调用一个类的静态变量方法时,如果类没有进行过初始化会进行初始化;
使用 java.lang.reflect 包的方法对类型进行反射调用时,如果类没有进行过初始化会进行初始化;
如果类进行初始化时,发现父类没有初始化过,会先去初始化父类;
启动类会被主动加载(main方法类);
当使用动态语言支持时,如果一个 java.lang.invoke.MethodHandle 实例最后解析结果是 PEF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial 四种类型的方法句柄,并且方法句柄对应的类型没有进行初始化,则需要首先触发初始化。
当一个接口中定义了JDK 8 的默认方法时候(default 修饰的接口方法),如果这个类的实现类进行初始化,那该接口会在其之前进行初始化。
public class Student {String name;String gender;public Student() {}}public class TestLoad {public static void main(String[] args) {Class<Student> studentClass = Student.class;}}

通过类的全限定名获取此类的二进制字节流;
将字节流所代表的静态存储结构转化为方法区的运行时数据结构(类元信息,比如字段,接口,方法等)
在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区中该类数据的入口。
文件格式验证,比如开头是否是 0XCAFEBABE 开头,检查常量池中的常量类型是否支持等; 元数据验证,主要对元数据的语义进行校验,比如该类父类是否被final修饰,是否实现了抽象父类或接口的所有方法等;
字节码验证,主要校验字节码内语法是否合法、符合逻辑;
符号引用验证:这个阶段发生在解析阶段(符号引用转换为直接引用),校验符号引用,比如判断通过全限定名是否能够找到对应类和关键字访问权限等。
// 在准备阶段a的值为0static int a = 1;// 在准备阶段b的值为1final static b = 1;
符号引用:其实就是一个字符串,但是通过这个字符串可以唯一标记一个类的方法、字段。
直接引用:直接引用就是指向目标具体的指针或内存中的相对偏移量(方法区)。

loadClass():进行类加载的方法,双亲委派模型的逻辑就在这个方法里
findClass():真正进行类加载的方法,将class文件加载成二进制字节流到内存
defineClass():通过内存二进制字节码字节流生成一个java.lang.Class对象
// ClassLoader$loadClass源码protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{// 加锁保证并发时的类加载synchronized (getClassLoadingLock(name)) {// 检查类是否被加载Class<?> c = findLoadedClass(name);// 如果类没有被加载if (c == null) {long t0 = System.nanoTime();try {// 如果父加载器不为空就委托给父类加载器if (parent != null) {c = parent.loadClass(name, false);} else {// 为空代表顶层是启动类加载器或自定义类加载器没设置父类加载器// 交给启动类加载器加载c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// 父类加载器加载失败后会抛出ClassNotFoundException异常// 子类加载器catch异常后,调用自己的findClass()方法进行加载}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();// 根据名称或位置加载.class字节码c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}
// 锁对象集合:key->value, 全类名->ObjectLockprivate final ConcurrentHashMap<String, Object> parallelLockMap;// ClassLoader$getClassLoadingLock源码protected Object getClassLoadingLock(String className) {Object lock = this;if (parallelLockMap != null) {Object newLock = new Object();// 以全类名为key,如果不存在就set,并将该key的value返回lock = parallelLockMap.putIfAbsent(className, newLock);if (lock == null) {lock = newLock;}}return lock;}

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysql", "账号", "密码");
// Driver注册集合private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();// Worker method called by the public getConnection() methods.private static Connection getConnection(for(DriverInfo aDriver : registeredDrivers) {// 检查该类加载器是否有权限加载Driverif(isDriverAllowed(aDriver.driver, callerCL)) {try {println("trying " + aDriver.driver.getClass().getName());// 通过url、账号、密码等信息获取链接,如果为null就遍历下一个Connection con = aDriver.driver.connect(url, info);if (con != null) {// Success!println("getConnection returning " + aDriver.driver.getClass().getName());return (con);}} catch (SQLException ex) {if (reason == null) {reason = ex;}}} else {println("skipping: " + aDriver.getClass().getName());}}}
// DriverManager类内的静态方法去加载驱动static {loadInitialDrivers();println("JDBC DriverManager initialized");}
// DriverManager类内的loadInitialDrivers()方法private static void loadInitialDrivers() {ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);Iterator<Driver> driversIterator = loadedDrivers.iterator();try{// 内部实现了迭代器,在调用next方法时候去真正加载类while(driversIterator.hasNext()) {driversIterator.next();}} catch(Throwable t) {// Do nothing}return null;}
public static <S> ServiceLoader<S> load(Class<S> service) {// 使用线程上下文加载器,可以显示指定,默认是AppClassLoader,ClassLoader cl = Thread.currentThread().getContextClassLoader();// 使用线程上下文加载器去发现服务并加载return ServiceLoader.load(service, cl);}
// 内部重写迭代器的hasNext方法public boolean hasNext() {if (acc == null) {// 该方法根据路径寻找SPI配置的全类名return hasNextService();} else {PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {public Boolean run() { return hasNextService(); }};return AccessController.doPrivileged(action, acc);}}// SPI配置路径private static final String PREFIX = "META-INF/services/";private boolean hasNextService() {if (nextName != null) {return true;}if (configs == null) {try {// 拼成全类名String fullName = PREFIX + service.getName();if (loader == null)configs = ClassLoader.getSystemResources(fullName);elseconfigs = loader.getResources(fullName);} catch (IOException x) {fail(service, "Error locating configuration files", x);}}}

// 内部重写迭代器的next方法public S next() {if (acc == null) {return nextService();} else {PrivilegedAction<S> action = new PrivilegedAction<S>() {public S run() { return nextService(); }};return AccessController.doPrivileged(action, acc);}}private S nextService() {if (!hasNextService())throw new NoSuchElementException();String cn = nextName;nextName = null;Class<?> c = null;try {// 根据全类名和设置的AppClassLoader去加载SPI实现类c = Class.forName(cn, false, loader);} catch (ClassNotFoundException x) {fail(service,"Provider " + cn + " not found");}if (!service.isAssignableFrom(c)) {fail(service,"Provider " + cn + " not a subtype");}try {// 实例化S p = service.cast(c.newInstance());// 放进providers集合,后续根据全类名找SPI实现providers.put(cn, p);return p;} catch (Throwable x) {fail(service,"Provider " + cn + " could not be instantiated",x);}throw new Error(); // This cannot happen}
public interface SpiService {public void spiMethod();}public class SpiServiceImpl implements SpiService {@Overridepublic void spiMethod() {System.out.println("快关注「阿东编程之路」!");}}
com.beiting.spi.impl.SpiServiceImpl
public abstract class SpiManager {// 服务注册集合private static final Map<String, SpiService> spiServices = new ConcurrentHashMap();private static final SpiService defaultService = new DefaultSpiService();static {loadSpiServices();}// SPI服务发现和注册逻辑private static void loadSpiServices() {ServiceLoader<SpiService> load = ServiceLoader.load(SpiService.class);Iterator<SpiService> iterator = load.iterator();while (iterator.hasNext()) {SpiService next = iterator.next();spiServices.put(next.getClass().getName(), next);}}// 获取SPI实现public static SpiService getSpiService(String name) {return spiServices.getOrDefault(name, defaultService);}// 默认SPI方法实现static class DefaultSpiService implements SpiService {@Overridepublic void spiMethod() {System.out.println("和阿东一起进步!");}}}
public class SpiDemo {public static void main(String[] args) {// 自定义SPI方法实现SpiManager.getSpiService("com.beiting.spi.impl.SpiServiceImpl").spiMethod();// 默认实现SpiManager.getSpiService("xxx").spiMethod();}}

!
文章转载自阿东编程之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




