java 类的加载
加载是将class文件加载到 jvm内存,并为之创建一个大的Class,任何类被系统使用都会建立一个大Class对象。Class用来表示文件内容,成员变量,构造方法,成员方法
连接:
验证是否是正确的Class内部结构
准备负责为静态成员分配内存,并设置默认初始值
解析将类的二进制符号符号替换为直接引用(例如地址值,替换为直接指向 )
类的加载时间
1.创建类实例时 new。
2.为静态[变量]赋值,访问静态变量
3.调用静态方法
4.使用反射方法创建某个类或接口的反射方法java.lang.Class
5.初始化某子类
6.通过java.exe调用类的方法时
类加载器
根类加载器
扩展类加载器
系统类加载
其他加载方式都是属于被动加载,不会导致类的加载和初始化 例如: 构造类的数组
Simple[] simples = new Simple[10];
新建了一个Simple数组,但是并不会导致Simple类的初始化,该操作只是在内存堆中开辟了一段连续地址空间.
引用静态[常量]不会导致该类的初始化.
类的加载阶段
类的加载就是将class的二进制读取到内存中,然后将字节流静态存储结构转换为方法去中运行的数据结构,并在堆中生成该类的Class对象,作为入口.
类加载的最终就是堆中的一个对象,不管被加载多少次,对应堆中对象始终是同一个, 在栈中形成对对象的引用.
类的连接阶段
public class LinkedPrepare {
private static int a = 10;
private final static int b = 10;
}
static int a = 10 在准备阶段不是10 ,而是初始化的值0,当然final static int b 则仍然是10,因为被final修饰的静态变量不会导致类的初始化
类初始化
类的初始化阶段所有的变量都会被赋予正确的值,也就是在编写程序时指定的值
静态语句块只能对后面的静态变量进行赋值,但是不能对其进行调用,否则无法通过编译.
public class classInit{
static{
System.out.print(x);
x = 1000;
}
private static int x = 10;
}
类变量的赋值顺序和静态代码块的执行代码,编译器的收集顺序,由在源文件中出现顺序决定. 父类的静态变量总能优先与子类的赋值
静态代码块保证了在同一时间只会被执行一次
public class Singleton{
// 1
private static int x = 0;
private static int y;
// 2
private static Singleton instance = new Singleton();
private Singleton(){
x++;
y++;
}
}
初始化结果语句放在1处,和2处的结果不同 放在2 处连接阶段, x = 0, y = 0, instaance = null; 初始化类阶段按顺序赋值真实初始化值, x = 0, y = 0, instance = new Singleton()调用构造方法 x = 1, y = 1
但是放在1 处 ,连接阶段 x = 0, y = 0 ,instance = null; 初始化阶段 instance = new Singleton() ,x = 1,y = 1 , 按顺序赋值 x = 0 ,y不变 y = 1;
类加载器
类加载器之间严格遵守父委托机制
- Bootsrap 根加载器
主要负责核心类库的加载,例如java.lang 包加载
- 扩展类加载器
扩展类加载器的父类是根加载器,主要用于加载java_home 下的jrelibext里面的类库,java实现,可以将自己实现的类打包放到下面加载.
- 系统类加载器
负责加载classpath下的类库资源
双亲委托机制
当一个类加载器调用loadclass之后,它并不会直接将其进行加载,而是先交给当前类加载器的父加载器尝试加载直到最顶层的父加载器,然后再依次向下进行加载.
线程上下文类加载器
JVM类加载器双亲委托机制的自身缺陷,JDK提供了很多SPI,例如JDBC,JNDI接口,具体的实现有各个不同的厂家进行提供,想要更换连接器,只需要切换即可,但是例如JDBC的接口是由根加载器进行加载,但是第三方驱动则由系统类加载器加载,如何解决问题,通过 Thread的上下文加载器,允许子委托机制进行加载.
- GO语言常用的文件读取方式
- GO语言文件的创建与打开实例分析
- Go语言单链表实现方法
- Go语言实现AzDG可逆加密算法实例
- 剖析Go编写的Socket服务器模块解耦及基础模块的设计
- Golang中的sync.WaitGroup用法实例
- Go 语言实现 MapReduce 框架
- Performance Schema使用简介(一)
- golang 垃圾回收 gc
- Go语言服务器开发之简易TCP客户端与服务端实现方法
- 移动搜索SEO分享:PHP自动生成百度开放适配及360移动适配专用的Sitemap文件
- 分享两种外链跳转方法,可避免权重流失。
- go语言十大排序算法总结
- 网站安全检测提示“页面异常导致本地路径泄漏”的解决办法
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Java常用设计模式--三种工厂模式之简单工厂模式(Simple Factory)
- Java常用设计模式--三种工厂模式之工厂模式(Factory Pattern)
- Java常用设计模式--三种工厂模式之抽象工厂模式(Abstract Factory Pattern)
- Mongodb只读副本集如何切换到读写模式
- Java常用设计模式--策略模式(Strategy Pattern)
- Mongodb只读副本集如何切换到读写模式(下)
- 手把手带你搭建redis集群
- Jvm常量池、运行时常量池、字符串常量池理解
- 【Docker】命令使用大全
- Apache如何设置Enable Keep-Alive
- 【Docker】项目实战,部署自己的APP
- 用云开发快速构建最美AI毕业照小程序
- 13-2 vi-启动和退出
- Java中四种引用类型:强引用,软引用,弱引用,虚引用
- docker-compose搭建redis集群之哨兵模式