Java类、类加载过程及多态

谈到java类,那我们不得不扒一下类的加载和类的详细信息以及类的双亲加载模型。

类文件结构

类一般由魔数、Class文件版本,常量池,访问标志,类索引、父类索引、接口索引集合、字段表集合、方法表集合、属性表集合组成。
详细内容可参看这篇文章
类文件源码

package exceptiontest;

public class ClassName {

    private int prvFiled = 1;
    public static final int psfFild = 2;

    protected String proMethod(String paras, Integer parsI) {
        return paras + parsI;
    }

}

我们可以用命令

javap –verbose classname

来查看编译后的类信息,部分图如下


1523847721(1).jpg

由于编译后的class文件较为复杂,我就不在这里进行分析。

类加载机制

说了类的文件结构,我们来说说类加载机制。

类加载器

类加载器是一个用来加载类文件的类。Java源代码通过javac编译器编译成类文件。然后JVM来执行类文件中的字节码来执行程序。类加载器负责 加载文件系统、网络或其他来源的类文件。

有三种默认使用的类加载器:Bootstrap类加载器、Extension类加载器和Application类加载器。每种类加载器都有设定好从哪里加载类。

Bootstrap类加载器负责加载rt.jar中的JDK类文件,它是所有类加载器的父加载器。Bootstrap类加载器没有任何父类加载 器,如果你调用String.class.getClassLoader(),会返回null,任何基于此的代码会抛出 NUllPointerException异常。Bootstrap加载器被称为初始类加载器。

Extension加载类的请求先委托给它的父加载器,也就是Bootstrap,如果没有成功加载的话,再从jre/lib/ext目录下 或者java.ext.dirs系统属性定义的目录下加载类。Extension加载器由 sun.misc.Launcher$ExtClassLoader实现。

Application类加载器它负责从classpath环境变量中加载某些应用相 关的类,classpath环境变量通常由-classpath或-cp命令行选项来定义,或者是JAR中的Manifest的classpath属性。 Application类加载器是Extension类加载器的子加载器。通过sun.misc.Launcher$AppClassLoader实现。
除了Bootstrap类加载器是大部分由C来写的,其他的类加载器都是通过java.lang.ClassLoader来实现的。

总结一下,下面是三种类加载器加载类文件的地方:

  1. Bootstrap类加载器 – JRE/lib/rt.jar
  2. Extension类加载器 – JRE/lib/ext或者java.ext.dirs指向的目录
  3. Application类加载器 – CLASSPATH环境变量, 由-classpath或-cp选项定义,或者是JAR中的Manifest的classpath属性定义.

类加载过程

类的加载要经过三步:装载(Load),链接(Link),初始化(Initializ)。其中链接又可分为校验(Verify),准备(Prepare),解析(Resolve)三步。

加载

ClassLoader就是用来装载的。通过指定的className,找到二进制码,生成Class实例,放到JVM中。

链接

链接就是把load进来的class合并到JVM的运行时状态中。可以把它分成三个主要阶段:

校验

对二进制字节码的格式进行校验,以确保格式正确、行为正确。这一阶段主要是为了确保Class文件的字节流中包含的信息复合当前虚拟机的要求,并且不会危害虚拟机自身的安全。主要验证过程包括:
1.文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。
2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。
3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。
4.符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。
准备:准备类中定义的字段、方法和实现接口所必需的数据结构。比如会为类中的静态变量赋默认值(int等:0, reference:null, char:’\u0000′)。

准备

正式为类变量分配内存并设置初始值。这里的初始值并不是初始化的值,而是数据类型的默认零值。这里提到的类变量是被static修饰的变量,而不是实例变量。关于准备阶段为类变量设置零值的唯一例外就是当这个类变量同时也被final修饰,那么在编译时,就会直接为这个常量赋上目标值。
如:
pirvate static int size = 12;
那么在这个阶段,size的值为0,而不是12。 final修饰的类变量将会赋值成真实的值。

解析

装入类所引用的其他所有类,虚拟机将常量池中的符号引用替换为直接引用。可以用许多方式引用类:超类、接口、字段、方法签名、方法中使用的本地变量。

初始化

在准备阶段,变量已经赋过一次系统要求的初始值,在初始化阶段,则是根据程序员通过程序的主观计划区初始化类变量和其他资源。
类初始化前,它的直接父类一定要先初始化(递归),但它实现的接口不需要先被初始化。类似的,接口在初始化前,父接口不需要先初始化。

多态原理

这里我们谈一谈多态原理
首先澄清几个概念,因为我在看这里的时候也特别容易混淆和迷惑。首先是符号引用。

符号引用

符号引用是一个字符串,它给出了被引用的内容的名字并且可能会包含一些其他关于这个被引用项的信息——这些信息必须足以唯一的识别一个类、字段、方法。这样,对于其他类的符号引用必须给出类的全名。对于其他类的字段,必须给出类名、字段名以及字段描述符。对于其他类的方法的引用必须给出类名、方法名以及方法的描述符。

方法签名

对于同名不同类、同类不同名的方法,方法签名的意义并不是很大,但是对于重载方法来说,方法签名的意义就十分巨大了。由于重载方法之间的方法名是相同的,那么我们势必要从构成方法的其他几个要素中找到另一个要素与方法名组成能够唯一标示方法的签名,方法体当然不予考虑。那么就是形参列表和返回值了,但是由于对于调用方法的人来说,方法的形参数据类型列表的重要程度要远远高于返回值,所以方法签名就由方法名+形参列表构成,也就是说,方法名和形参数据类型列表可以唯一的确定一个方法,与方法的返回值一点关系都没有,这是判断重载重要依据

在类加载过程中的解析阶段,会将常量池中符号引用替换为直接引用。但是只是替换了部分。我们看下面一段话:
(1) 所有私有方法、静态方法、构造器及初始化方法都是采用静态绑定机制。在编译器阶段就已经指明了调用方法在常量池中的符号引用,JVM运行的时候只需要进行一次常量池解析即可。

(2) 类对象方法的调用必须在运行过程中采用动态绑定机制。
首先,根据对象的声明类型(对象引用的类型)找到“合适”的方法。具体步骤如下:
① 如果能在声明类型中匹配到方法签名完全一样的方法,那么这个方法是最合适的。
② 在第①条不能满足的情况下,寻找可以“凑合”的方法。标准就是通过将参数类型进行自动转型之后再进行匹配。如果匹配到多个自动转型后的方法签名f(A)和f(B),则用下面的标准来确定合适的方法:传递给f(A)方法的参数都可以传递给f(B),则f(A)最合适。反之f(B)最合适 。
③ 如果仍然在声明类型中找不到“合适”的方法,则编译阶段就无法通过。

最后,根据在堆中创建对象的实际类型找到对应的方法表,从中确定具体的方法在内存中的位置。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容