Jvm结构 类加载的学习

Jvm结构 类加载

类加载子系统的作用

类加载子系统负责从文件系统或者网络中加载class文件,class文件开头有特定的文件标识,(字节码文件都以CA FE BA BE标识开头)

classLoader只负责class文件的加载,至于它是否可以允许,泽由ExcecutionEngine决定,加载的类信息存放于一块称之为方法区的内存空间,除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量

类加载ClassLoader的角色

1.classfile(class文件)存在于硬盘上,可以理解为设计师画在纸上的模板,最终这个模板执行的时候是要加载JVM中来,根据这个模板实例化出n个一模一样的实例.

2.classfile 加载到jvm中,被称为DNA元数据模板,放在方法中去

3.在class----->jvm-------->最终被称为元数据模板,此过程就要有一个运输工具(类加载器 class loader)扮演一个快递员的角色

JVM类加载过程

加载--------验证---------准备------------解析-----------------初始化

也可以说 加载-链接-初始化

加载:

1.通过类名,获取此类的二进制字节流

2.将这个字节流所代表的静态存储结构转化为方法区(元空间)的运行时结构

3,在内存中生成一个代表这个类的java.lang.class对,作为方法区这个类的各种数据的访问入口

链接

链接部分分为三步,

验证:检验被加载的类是否有正确的内部结构,并与其他类协调一致
准备:准备阶段则负责为类的静态属性分配内存,并设置默认初始值

不包含用final修饰的static实例变量,在编译时进行初始化,不会为实例变量初始化,

解析:将类的二进制数据中的符号引用替换成直接引用,

符号引用是用户一组符号描述所引用的目标,直接引用是指向目标的指针

初始化

类什么时候会初始化?

1创建类的实例,也就是创建一个对象

2访问某个类或者接口的静态变量,或者对该静态变量赋值

3调用类的静态方法

4反射()Class.forName("")

5,初始化一个类的子类(会首先初始化子类的父类)

类的初始化顺序

对static修饰的变量或者语句块进行赋值,

如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行

如果初始化一类的时候,其有父类而且父类没有被初始化,则优先初始化它的父类

顺序是:父类static 子类static 父类构造方法 子类构造方法

类加载器的分类

JVM支持两种类型的类加载器,分别为引导类加载器,和自定义类加载器

无论类加载器的类型怎么划分,在程序中我们最常见的始终有三个

引导类加载器(也就是启动类加载器)

这个类加载器使用c/c++语言实现,嵌套在jvm内部,他用来加载java核心类库

并不集成于java.lang.ClassLoader没有父加载器(孤儿)

负责加载扩展类加载器和应用类加载器,并为他们制定父类加载器

出于安全考虑,引用类加载器只加载包名为java,javax,sun开头的类

扩展类加载器

java语言编写的,由sun,misc,Launcher$ExtClassLoader实现

派生于ClassLoader类,上层加载器类引用类加载器(有爹不是孤儿)

从java.ext.dirs系统属性所指定的目录中加载类库,或者从JDK系统安装目录的,jre/lib/ext子目录下加载类库,如果用户创建的jar放在此目录下,也会自动由扩展类加载器加载

应用程序类加载器,(系统类加载器)

java语言编写的,由 sun.misc.Launcher$AppClassLoader 实现.

派生于classLoader类 上层类加载器为扩展类加载器

来加载我们自己定义的类 该类加载器是程序中默认的类加载器

通过类名.class.getClassLoader(),ClassLoader.getSystemClassLoader()来获得.

ClassLoader 类,它是一个抽象类,其后所有的类加载器都继承自 ClassLoader

(不包括启动类加载器)

双亲委派机制

java虚拟机对class文件采取的是按需加载的方式,也就是说当需要该类是才会将它的class文件加载到内存中生成class对象,而且加载某个类的class文件时,java虚拟机采用的是双亲委派机制,

工作原理;

如果一个类加载器收到了类加载请求,它会把请求交给父类加载器执行,如果父类加载器还有父亲,则进一步向上委托,最后父类如果加载失败,就交由子加载器自己处理

如果全部失败:就会抛出ClassNotFoundException异常

双亲委派的优点:

1,安全 可避免用户自己编写的类动态替换java的核心类,如java.lang.String

2 避免全限定命名的类重复加载

沙箱安全机制:

作用;防止代码被污染

面试题:

在jvm中如何判断两个对象属于同一类?

类的全类名完全一致.类的加载器必须相同

类的主动使用

主动使用:

通过new关键字被导致类的初始化,这是大家经常使用的初始化一个类的方式,

他肯定会导致类的加载并且初始化

访问类的静态变量,包括读取和更新

访问类的静态方法

对某个类进行反射操作,会导致类的初始化

初始化子类会导致父类的的初始化

执行该类的 main 函数

被动使用:

其实除了上面的几种主动使用其余就是被动使用了

1.引用该类的静态常量,注意是常量,不会导致初始化,但是也有意外,这里的常量

是指已经指定字面量的常量,对于那些需要一些计算才能得出结果的常量就会导

致初始化,比如:

public final static int NUMBER = 5 ; //不会导致类初始化,被动使用public final static int RANDOM = new Random().nextInt() ; //会导致类的初

始化,主动使用

2.构造某个类的数组时不会导致该类的初始化,比如:

Student[] students = new Student[10] ;

主动使用和被动使用的区别在于类是否会被初始化.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值