java加载器什么时候加载类,java中静态内部类什么时候加载
大家好,关于java加载器什么时候加载类很多朋友都还不太明白,今天小编就来为大家分享关于java中静态内部类什么时候加载的知识,希望对各位有所帮助!
Java中的类是什么时候被加载到虚拟机
这个问题java的比较核心的一个难题,我就针对问题做简要回答,不做深入讨论了:
1、编译和运行概念要搞清:编译即javac的过程,负责将.java文件compile成.class文件,主要是类型、格式检查与编译成字节码文件,而加载是指java*的过程,将.class文件加载到内存中去解释执行,即运行的时候才会有加载一说。
2、类的加载时机,肯定是在运行时,但并不是一次性全部加载,而是按需动态,依靠反射来实现动态加载,一般来说一个class只会被加载一次,之后就会从jvm的class实例的缓存中获取,谁用谁取就可以了,不会再去文件系统中加载.class文件了。
明白1,2点就够了,再深入要等一段才能明白了。
java中类加载器是怎么工作的
JVM将类加载过程分为三个步骤:装载(Load),链接(Link)和初始化(Initialize)
链接又分为三个步骤,验证、准备、解析
1)装载:查找并加载类的二进制数据;
2)链接:
验证:确保被加载类的正确性;
准备:为类的静态变量分配内存,并将其初始化为默认值;
解析:把类中的符号引用转换为直接引用;
3)初始化:为类的静态变量赋予正确的初始值;
那为什么我要有验证这一步骤呢?首先如果由编译器生成的class文件,它肯定是符合JVM字节码格式的,但是万一有高手自己写一个class文件,让JVM加载并运行,用于恶意用途,就不妙了,因此这个class文件要先过验证这一关,不符合的话不会让它继续执行的,也是为了安全考虑吧。
准备阶段和初始化阶段看似有点牟盾,其实是不牟盾的,如果类中有语句:private static int a= 10,它的执行过程是这样的,首先字节码文件被加载到内存后,先进行链接的验证这一步骤,验证通过后准备阶段,给a分配内存,因为变量a是static的,所以此时a等于int类型的默认初始值0,即a=0,然后到解析(后面在说),到初始化这一步骤时,才把a的真正的值10赋给a,此时
java中静态内部类什么时候加载
只有在加载内部类的时候才初始化
看懂以下的代码,那么对于类的加载,基本上就没问题了,最后类的加载过程的解释
public class Test6{
public static void main(String[] args){
new B();
new A.C();
}
}
class A{
private P p1= new P("A--p1");
static P p3= new P("A--p3");
public A(){
System.out.println("A()");
}
private P p2=new P("A--p2");
static{
new P("A--static");
}
{new P("A{...}");}
public static class C{
private P p1= new P("C--p1");
static P p3= new P("C--p3");
public C(){
System.out.println("C()");
}
private P p2=new P("C--p2");
static{
new P("C--static");
}
{new P("C{...}");}
}
}
class B extends A{
private P p1= new P("B--p1");
static P p3= new P("B-- p3");
public B(){
System.out.println("B()");
}
public P p2= new P("B-- p2");
static{
new P("B-- static");
}
{new P("B{...}");}
}
class P{
public P(String s){
System.out.println(s);
}
}
/*
有父类的情况
1.加载父类
1.1为静态属性分配存储空间并赋初始值
1.2执行静态初始化块和静态初始化语句(从上至下)
2.加载子类
2.1为静态属性分配存储空间
2.2执行静态初始化块和静态初始化语句(从上至下)
3.加载父类构造器
3.1为实例属性分配存数空间并赋初始值
3.2执行实例初始化块和实例初始化语句
3.3执行构造器内容
4.加载子类构造器
4.1为实例属性分配存数空间并赋初始值
4.2执行实例初始化块和实例初始化语句
4.3执行构造器内容
5回到main()
内部类的加载过程也一样
java的类加载后什么时候会被释放
java的类加载后且当使用阶段完成之后,java类就进入了卸载阶段,也就是所谓的释放。
使用阶段包括主动引用和被动引用,主动饮用会引起类的初始化,而被动引用不会引起类的初始化。
一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况,如图所示:
PS:关于类的卸载,在类使用完之后,如果满足下面的情况,类就会被卸载:
该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
加载该类的ClassLoader已经被回收。
该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
如果以上三个条件全部满足,jvm就会在方法区垃圾回收的时候对类进行卸载,类的卸载过程其实就是在方法区中清空类信息,java类的整个生命周期就结束了。
好了,本文到此结束,如果可以帮助到大家,还望关注本站哦!