当前位置: 首页 > >

Java Class类结构

发布时间:

1. class文件结构
1. 魔数与Class文件的版本


Class文件头4个字节为魔数(Magic Number),为0xCAFEBABE。


紧接着4个字节为Class文件的版本号,第5、6字节为次版本号,第7、8字节为主版本号。



2. 常量池

常量池中主要存放两大类常量:字面量和符号引用。字面量比较接*于java语言层面的常量概念,如文本字符串、声明为final的常量值等。而符号引用则属于编译原理方面的概念,包括了下面三类常量:


    类和接口的全限定名。字段名称和描述符。方法的名称和描述符。


3. 访问标志

用于识别一些类或者接口层次等访问信息,包括:这个Class是类还是接口;是否定义为public类型;是否定义为abstract类型;如果是类的话,是否被声明为final等。



4. 类索引、父类索引与接口索引集合

这三项数据来确定这个类等继承关系。



5. 字段表集合

用于描述接口或者类中声明的变量。



6. 方法表集合

用于描述方法。



7. 属性表集合
2. Class文件生命周期

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:


1. 加载(Loading)

此阶段完成三件事情:


    通过一个类等全限定名来获取定义此类等二进制字节流。将这个字节流所代表的静态存储结构转化为方法区等运行时数据结构。在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据等访问入口。


2. 验证(Verification)

大致完成下面4个阶段等检验动作:


    文件格式验证。元数据验证。字节码验证。符号引用验证。


3. 准备(Preparation)

准备阶段是正式为类变量分配内存并设置类变量初始值(类型初始值)的阶段,这些变量所使用等内存都将在方法区中进行分配。



4. 解析(Resolution)

解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。



5. 初始化(Initialization)

根据程序员通过程序制定的主观计划去初始化类变量和其他资源,从另外一个角度去表达就是:初始化阶段是执行类构造器clinit()方法的过程。



6. 使用(Using)
7. 卸载(Unloading)
3. 类与类加*

对于任意一个类,都需要由加载它的类加*骱驼飧隼啾旧硪煌妨⑵湓趈ava虚拟机中的唯一性,每一个类加*鳎加涤幸桓龆懒⒌睦嗝瓶占洹U饩浠氨泶锏母ㄋ滓恍罕冉狭礁隼嗍欠瘛跋嗟取保挥性谡饬礁隼嗍怯赏桓隼嗉釉*骷釉氐惹疤嵯虏庞幸庖澹裨颍词拐饬礁隼嗬丛从谕桓鯟lass文件,被同一个虚拟机加载,只要加载他们的类加*鞑煌钦饬礁隼嗑捅囟ú幌嗟取


这里所指的“相等”,包括代表类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法返回结果,也包括使用instanceof关键字做对象所属关系判定等情况。



4. 双亲委派模型

三种系统提供的类加*鳎


1. 启动类加*鳎˙ootstrap ClassLoader)

这个类负责加载JAVA_HOME>lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的类库加载到虚拟机内存中。



2. 扩展类加*鳎‥xtension ClassLoader)

这个加*饔蓅un.misc.Launcher$ExtClassLoader实现,它负责加载JAVA_HOMElibext目录中的,或者被java.ext.dirsz系统变量所指定的路径中的所有类库,开发者可以直接使用扩展类加*鳌



3. 应用程序类加*鳎ˋpplication ClassLoader)

这个加*饔蓅un.misc.Launcher$AppClassLoader实现。由于这个类加*魇荂lassLoader中的getSystemClassLoader()方法的返回值,所以一般也称它为系统类加*鳌K涸鸺釉赜没Ю嗑纤付ǖ睦嗫猓⒄呖梢灾苯邮褂谜飧隼嗉釉*鳎绻τ贸绦蛑忻挥凶远ㄒ骞约旱睦嗉釉*鳎话闱榭鱿抡飧鼍褪浅绦蛑心系睦嗉釉*鳌


4. 双亲委派模型过程

如果一个类加*魇盏搅死嗉釉氐那肭螅紫炔换嶙约喝コ⑹约釉卣飧隼啵前颜飧銮肭笪懈咐嗉釉*魅ネ瓿桑恳桓霾愦蔚睦嗉釉*鞫际侨绱耍虼怂械募釉厍肭笞钪斩加Ω么偷蕉ゲ愕钠舳嗉釉*髦校挥械备讣釉*鞣蠢∽约何薹ㄍ瓿烧飧黾釉厍肭笫保蛹釉*鞑呕岢⑹宰约喝ゼ釉亍


JDK1.2之后已不提倡用户再去覆盖loadClass()方法,而应当把自己的类加载逻辑写到findClass()方法中,在loadClass()方法的逻辑里如果父类加载失败,则会调用自己的findClass()方法来完成加载,这样就可以保障新写出来的类加*魇欠纤孜晒嬖虻摹




转载于:https://blog.51cto.com/wenshengzhu/2317068



友情链接: