JVM中的类加载器

一个类被初始化的过程?

在这里插入图片描述
加载: classpath、jar包、网络、某个磁盘位置下的类的class二进制字节流读进来,在内存中生成一个代表这个类的java.lang.Class对象放入元空间,此阶段我们程序员可以干预,我们可以自定义类加载器来实现类的加载;
验证: 验证Class文件的字节流中包含的信息符合《Java虚拟机规范》的全部约束要求,保证虚拟机的安全;
准备: 类变量赋默认初始值,int为0,long为0L,boolean为false,引用类型为null;常量赋正式值;
解析: 把符号引用翻译为直接引用;
**初始化:**我们new一个类的对象,访问一个类的静态属性,修改一个类的静态属性,调用一个类的静态方法,用反射API对一个类进行调用,初始化当前类,其父类也会被初始化… 那么这些都会触发类的初始化;(赋真正的值)
使用: 使用这个类;
卸载:
1.该类所有的实例都已经被GC,也就是JVM中不存在该Class的任何实例;
2.加载该类的ClassLoader已经被GC;
3.该类的java.lang.Class 对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的方法;

静态变量==准备
public static final Stringstr="测试"
静态变量==准备阶段赋值为null,初始化阶段赋值为  静态变量
public static Stringstr="测试1"
变量==创建对象的时候赋值(new 对象的时候)
public String filed="水电费"
静态代码块===初始化阶段的时候执行
static{

}
非静态代码块==创建对象的时候执行(new 对象的时候)
{
}
构造器==创建对象的时候执行(new 对象的时候)

继承时父子类的初始化顺序是怎样的?

父类–静态变量
父类–静态初始化块
子类–静态变量
子类–静态初始化块
父类–变量
父类–初始化块
父类–构造器
子类–变量
子类–初始化块
子类–构造器

JVM中不同的类加载器加载哪些文件?

1、启动类加载器(Bootstrap ClassLoader):(根的类加载器)C++语言实现的
<JAVA_HOME>\jre\lib\rt.jar,resources.jar、charsets.jar
被-Xbootclasspath参数所指定的路径中存放的类库;
2、扩展类加载器(Extension ClassLoader):
sun.misc.Launcher$ExtClassLoader,
<JAVA_HOME>\jre\lib\ext,
被java.ext.dirs系统变量所指定的路径中所有的类库;

3、应用程序类加载器(Application ClassLoader):系统的类加载器
sun.misc.Launcher$AppClassLoader
加载用户类路径(ClassPath)上所有的类库;

JVM类加载的双亲委派模型

在这里插入图片描述
双亲委派模型的工作过程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当上一层类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到这个类)时,下一层类加载器才会尝试自己去加载;

JDK为什么要设计双亲委派模型,有什么好处?

  • 确保安全,避免Java核心类库被修改;
  • 避免重复加载
  • 保证类的唯一性

可以打破JVM双亲委派模型吗?如何打破JVM双亲委派模型?

可以
想要打破这种模型,那么就自定义一个类加载器,重写其中的loadClass方法,使其不进行双亲委派即可;

如何自定义自己的类加载器?

1、继承ClassLoader
2、覆盖findClass(String name)方法 或者 loadClass() 方法;
findClass(String name)方法 不会打破双亲委派;
loadClass() 方法 可以打破双亲委派;

ClassLoader中的loadClass()、findClass()、defineClass()区别?

loadClass() 就是主要进行类加载的方法,默认的双亲委派机制就实现在这个方法中;
findClass() 根据名称或位置加载.class字节码;
definclass() 把字节码转化为java.lang.Class;
1、当我们想要自定义一个类加载器的时候,并且想破坏双亲委派模型时,我们会重写loadClass()方法;
2、如果我们想定义一个类加载器,但是不想破坏双亲委派模型的时候呢?可以可以重写findClass方法(),findClass()方法是JDK1.2之后的ClassLoader新添加的一个方法,这个方法只抛出了一个异常,没有默认实现;
JDK1.2之后已不再提倡用户直接覆盖loadClass()方法,而是建议把自己的类加载逻辑实现到findClass()方法中;
所以,如果你想定义一个自己的类加载器,并且要遵守双亲委派模型,那么可以继承ClassLoader,并且在findClass()中实现你自己的加载逻辑即可;

Class.forName和Classloader.loaderClass的区别

Class.forName得到的class是以及初始化完成的
Classloader.loaderClass得到的class还没有初始化的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值