博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jvm(36),class文件结构----访问标志
阅读量:6714 次
发布时间:2019-06-25

本文共 2511 字,大约阅读时间需要 8 分钟。

access_flags中一共有32个标志位可以使用,当前只定义了其中的8个,没有使用到的标志位要求一律为0

package org.fenixsoft.clazzpublic class TestClass{ private int mpublic int inc(){ return m+1

}}

access_flags中一共有16个标志位可以使用,当前只定义了其中8个[1],没有使用到的标志位要求一律为0。以代码清单6-1中的代码为例,TestClass是一个普通Java类,不是接口、枚举或者注解,被public关键字修饰但没有被声明为final和abstract,并且它使用了JDK

1.2之后的编译器进行编译,因此它ACC_PUBLIC、ACC_SUPER标志应当为真,而

ACC_FINAL、ACC_INTERFACE、ACC_ABSTRACT、ACC_SYNTHETIC、 ACC_ANNOTATION、ACC_ENUM这6个标志应当为假,因此它的access_flags的值应为:0x0001|0x0020=0x0021。从图6-5中可以看出,access_flags标志(偏移地址: 0x000000EF)的确为0x0021。

  1. 访问标志、类索引、父类索引、接口索引集合 在class文件中的位置

好,让我们来一一击破它们,看看它们到底是什么东西。

  1. 访问标志(access_flags)能够表示什么?

访问标志(access_flags)紧接着常量池后,占有两个字节,总共16位,如下图所示:

当JVM在编译某个类或者接口的源代码时,JVM会解析出这个类或者接口的访问标志信息,然后,将这些标志设置到访问标志(access_flags)这16个位上。JVM会考虑如下设置如下访问表示信息: a. 我们知道,每个定义的类或者接口都会生成class文件(这里也包括内部类,在某个类中定义的静态内部类也会单独生成一个class文件)。

对于定义的类,JVM在将其编译成class文件时,会将class文件的访问标志的第11位设置为1。第11位叫做ACC_SUPER标志位;对于定义的接口,JVM在将其编译成class文件时,会将class文件的访问标志的第8位 设置为1 。第8位叫做ACC_INTERFACE标志位

b.class文件表示的类或者接口的访问权限有public类型的和包package类型的。

如果类或者接口被声明为public类型的,那么,JVM将其编译成class文件时,会将class 文件的访问标志的第16位设置为1。第16位叫做ACC_PUBLIC标志符;

c. 类是否为抽象类型的,即我们定义的类有没有被abstract关键字修饰,即我们定义的类是否为抽象类。如果我们形如:

public abstract class MyClass{......}

定义某个类时,JVM将它编译成class文件的时候,会将class文件的访问标志的第7位设置为1。第7位叫做ACC_ABSTRACT标志位。 另外值得注意的是,对于定义的接口,JVM在编译接口的时候也会对class文件的访问标志上的ACC_ABSTRACT标志位设置为 1; d. 该类是否被声明了final类型,即表示该类不能被继承。 此时JVM会在编译class文件的过程中,会将class文件的访问标志的第12位设置为 1 。第12位叫做ACC_FINAL标志位; e.如果我们这个class文件不是JVM通过java源代码文件编译而成的,而是用户自己通过 class文件的组织规则生成的,那么,一般会对class文件的访问标志第4位设置为 1 。通过

JVM编译源代码产生的class文件此标志位为 0,第4位叫做ACC_SYNTHETIC标志位

  1. 枚举类,对于定义的枚举类如:public enum EnumTest{....},JVM也会对此枚举类编译成class文件,这时,对于这样的class文件,JVM会对访问标志第2位设置为 1 ,以表示它是枚举类。第2位叫做ACC_ENUM标志位
  2. 注解类,对于定义的注解类如:public @interface{.....},JVM会对此注解类编译成class 文件,对于这样的class文件,JVM会将访问标志第3位设置为1,以表示这是个注解类,第

3位叫做ACC_ANNOTATION标志位

当JVM确定了上述标志位的值后,就可以确定访问标志(access_flags)的值了。实际上 JVM上述标志会根据上述确定的标志位的值,对这些标志位的值取或,便得到了访问标志

access_flags)。如下图所示:

 

举例:定义一个最简单的类Simple.java,使用编译器编译成class文件,然后观察class文件中的访问标志的值,以及使用javap -v Simple 查看访问标志。

  1. package com.louis.jvm;
  2. publicclassSimple{
  1. }

使用UltraEdit查看编译成的class文件,如下图所示:

上述的图中黄色部分表示的是常量池部分,具体为什么是常量池部分不是本文的重点,有兴趣的读者可以参考我的《Java虚拟机原理图解》系列关于常量池的博客,你就可以很轻松地识别常量它们了。

常量池后面紧跟着就是访问标志,它的十六进制值为0x0021,二进制的值为:00000000 00100001,由二进制的1的位数可以得出第11、16位为1,分别对应ACC_SUPER标志位和ACC_PUBLIC标志位。

也可以通过一下运算:

0x0021 = 0x0001 | 0x0020, 即: 访问标志表示的标志是ACC_PUBLIC +

ACC_SUPER

为了验证我们的运算,使用javap -v Simple查看反编译信息如下:(小技巧:使用javap -v Simple指令的结果展示在命令提示符下显示不友好,一般我是使用javap -v Simple > temp.txt,将结果重定向到文件中,然后查看文件)

 

转载地址:http://szelo.baihongyu.com/

你可能感兴趣的文章
clamav杀毒软件部署笔记
查看>>
小测试
查看>>
涨姿势一下:#include<>和#include""的区别
查看>>
quartz spring配置
查看>>
centos备份与还原
查看>>
fixed 兼容ie6
查看>>
To Be an Architect : 架构的一些基本概念
查看>>
数据恢复软件哪个好
查看>>
『火车进出栈问题 卡特兰数』
查看>>
第四天:HTTP&Tomcat
查看>>
python 文件和路径操作函数小结
查看>>
条件+努力=?
查看>>
HBase分布式安装
查看>>
随笔-文件的读写
查看>>
tcp 状态以及三次握手
查看>>
我的友情链接
查看>>
WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK!的分析
查看>>
nginx禁止ip直接访问
查看>>
hadoop常用服务管理命令
查看>>
10.28 rsync工具10.29-10.30 rsync选项10.31 rsync通过ssh同步
查看>>