Java类加载理解

类的加载:

 指的是将class文件的二进制数据读入到运行时数据区(JVM在内存中划分的)中,并在方法区内创建一个class对象。

    类加载器:

     负责加载编译后的class文件(字节码文件)到JVM(Java虚拟机)当中。

        而类加载器主要分为以下几种:

       Bootstrap class loader 引导类加载器

         负责加载Java核心类库。在jre\lib目录下,包括rt.jar(Java基础类库),这些都是Java的核心类库。而且这个加载器是由C语言编写的,所以在Java程序中是获取不到的。

        Extension class loader扩展类加载器

         负责加载Java平台下扩展功能的jar包,这些jar包在jre\lib\ext目录下。这个加载器由Java语言编写的。

        System class loader系统类加载器

         负责加载classpath目录下的所有类库,classpath目录下的class文件一般是我们自己写的java文件编译后的。而这个加载器是由Java语言写的。这些类加载器协同起来完成整个类的加载过程,因此这些类的加载模式基于“委托模型”

    “双亲委托模型”

            程序运行后,编译器把Java文件编译成class文件后,首先负责加载的是系统类加载器,但它不会马上加载,而是将此任务移送给它的父类加载器扩展类加载器加载,扩展类加载器也是将此任务移送给引导类加载器加载。class文件到了引导类加载器那,它先判断能不能加载这个类,如果能,就加载;不能,移送给其子加载器,以此类推。最终我们编写的class都会配置在classpath环境中,所以,这个类加载任务还是由系统类加载器完成。如果系统类加载器都不能加载,就抛出ClassNotFoundException。当一个class加载到JVM中,类加载阶段已经完成。接下来JVM分配内存,对整个class文件(文件里面都是二进制的汇编命令)进行内容解析(JVM对二进制的命令逐行解析,交由CPU执行)。

内存分配:

 JVM运行起来时就给内存划分空间,这块空间就称为运行时数据区。

    运行时数据区被划分为以下几块内容:

    栈:

         每一个线程运行起来的时候就会对应一个栈(线程栈),栈中存放的数据被当前线程所独享(不会产生资源共享情况,所以线程是安全的)。而栈当中存放的是栈帧,当线程调用方法时,就是形成一个栈帧,并将这个栈帧进行压栈操作。方法执行完后,进行出栈操作。这个栈帧里面包括(局部变量,操作数栈,指向当前方法对应类的常量池引用,方法返回地址等信息)。

    本地方法栈:

         本地方法栈的机制和栈的相似,区别在于,栈运行的是Java实现的方法,而本地方法栈运行的是本地方法。本地方法指的是JVM需要调用非Java语言所实现的方法,例如C语言。在JVM规范中,没有强化性要求实现方一定要划分出本地方法栈(例如:HotSpot虚拟机将本地方法栈和栈合二为一)和具体实现(不同的操作系统,对JVM规范的具体实现都不一样)。

程序计数器:

         程序计数器也可以称为PC寄存器(通俗讲就是  指令缓存)。它主要用于缓存当前

程序下一条指令的指令地址,CPU根据这个地址找到将要执行的指令。这个寄存器是JVM内部实现的,不是物理概念上的计数器,不过和JVM的实现逻辑一样。

    堆:

        堆内存主要存放创建的对象和数组。堆内存在JVM中是唯一的,能被多个线程所共享。堆里面的每一个对象都存放着实例的实例变量。堆内存的对象没有被引用,会自动被Java垃圾回收机制回收。当在方法中定义了局部变量,如果这个变量是基本数据类型,那么这个变量的值就直接存放在栈中;如果这个变量是引用数据类型,那么变量值就存放在堆内存中,而栈中存放的是指向堆中的引用地址。

    方法区:

        方法区在JVM也是一个非常重要的一块内存区域,和堆一样,可以被多个线程多共享。主要存放每一个加载class的信息。class信息主要包含魔数(确定是否是一个class文件),常量池,访问标志(当前的类是普通类还是接口,是否是抽象类,是否被public修饰,是否使用了final修饰等描述信息......),字段表集合信息(使用什么访问修饰符,是实例变量还是静态变量,是否使用了final修饰等描述信息.....),方法表集合信息(使用什么访问修饰符,是否静态方法,是否使用了final修饰,是否使用了synchronized修饰,是否是native方法......)等内容。当一个类加载器加载了一个类的时候,会根据这个class文件创建一个class对象,class对象就包含了上述的信息。后续要创建这个类的实例,都根据这个class对象创建出来的。

    常量池:

        常量池是方法区中的一部分,存放class对象中最重要的资源。JVM为每一个class对象都维护一个常量池。它主要存储两种类型的常量:

       字面常量:

            字面常量通常就是在Java中定义的字面量值。例如:int = 1,中的 1,String s = "hello",这个hello就是字面量。或者使用final修饰的常量值。

        符号引用:

          符号引用主要包括类和接口的完整类名,属性的名称和描述符,方法名和描述符等。

 

 

转载于:https://my.oschina.net/u/3676895/blog/2236658

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值