Java 实现一次编译到处运行的基础,来源于 Java 虚拟机屏蔽了操作系统的底层细节。使用 class 文件存储编译后的源程序,使得 Java 程序的编译与操作系统解耦。正是因为 Java class 文件的设计与 Java 语言解耦,分别发布了 Java语言规范和 Java 虚拟机规范,使得其他语言如Scala、Groovy、JRuby、JPython 等基于Java 虚拟机的语言按照 class 文件格式要求生成的class 文件也能在虚拟机上运行。

class 文件格式

class 文件采用如下的结构存储二进制内容。其中 u2、u4 分别表示占用 2、4 个字节。

{

u4 magic; //魔数,固定为0xCAFEBABE

u2 minor_version; //次版本号

u2 major_version; //主版本号

u2 constant_pool_count; //常量池计数器

cp_info constant_pool[constant_pool_count-1]; //常量池

u2 access_flags; //访问标志,声明权限

u2 this_class; //类索引

u2 super_class; //父类索引

u2 interfaces_count; //接口个数

u2 interfaces[interfaces_count]; //接口列表

u2 fields_count; //字段个数

field_info fields[fields_count];//字段列表

u2 methods_count; //方法个数

method_info methods[methods_count]; //方法列表

u2 attributes_count; //属性个数

attribute_info attributes[attributes_count]; //属性列表

}

class 文件内容解读

常量池:

存储 class 文件用到的所有的字符串常量、类名、接口名、字段名以及其他常量。class 文件的其他项目往往会引用常量池中的常量,因此常量池容量计数从1开始,0 用于表示其他项目不引用常量池。在常量池中主要存储了字面量和符号引用两大类常量,字面量主要是字符串、final 类型常量值等,符号引用则包括类和接口的全限定名、字段的名称和描述法以及方法的名称和描述符。在前文《 Java 虚拟机类加载机制》中提到的符号引用转换为直接引用中的符号引用就是常量池中的符号引用。

访问标志:

类或接口的访问权限信息,包括 public、final、super、interface、abstract、annotation、enum 几种属性,以及使用 synthetic 表示非 Java 源码生成的代码。

类索引:

this_class 存储常量池中的一个索引,索引处的常量表示 class 文件定义的类或接口。如果这是一个类,super_class 为 0 或存储常量池中的一个索引,索引处的常量表示父类;如果这是一个接口,super_class 存储常量池中的一个索引,索引处的常量一定是 java.lang.Object。通过 this_class 可以确定当前类的全限定名,通过 super_class 可以确定父类的全限定名。

接口列表:

如果这是一个类,存储该类实现的接口列表,按照 implements 后的接口顺序存储;如果这是一个接口,存储该接口的所有父接口列表,按照 extends 后的接口顺序存储。

字段列表:

存储类或接口声明的变量,包括类变量和实例变量。描述了每个变量的信息,包括作用域、static、final、volatile、transient、类型、名称等。其中字段的名称、类型需要引用常量池中的常量来描述。

方法列表:

存储类或接口声明的方法,包括类方法和实例方法。描述了每个方法的信息,包括访问标志、名称索引、描述符索引、属性表集合等。这里仅仅存储了方法的信息,方法的实现代码编译成字节码后存储在属性表集合中的 “ Code ” 属性里面。

属性列表:虚拟机规范定义了大量的属性,class 文件、字段列表、方法列表都可以使用属性描述专有信息。而属性的名称需要引用常量池的常量来表示。方法体中的代码经编译后就存放在名为 Code 的属性中。

总结

Java 源程序编译后生成 class 文件而不是二进制可执行文件,通过 Java 虚拟机来解析并执行 class 文件中的程序,实现了“一次编译,到处运行”。在 class 文件中,存储了类或接口的基本信息,如版本号、类名、接口列表、字段列表、方法列表等。

原文地址:Java到处运行的基础之 Class 文件

Java到处运行的基础之 Class 文件的更多相关文章

  1. java 程序运行的基础知识【Java bytecode】

    聊聊文字,写一篇关于 java 基础知识的博文. JVM 线程栈 到 函数运行 每一个JVM线程来说启动的时候都会创建一个私有的线程栈.一个jvm线程栈用来存储栈帧,jvm线程栈和C语言中的栈很类似, ...

  2. [Java] Java 技术和 JVM 基础

    Java 由 Sun 公司在 1995 首次发布,既是一门编程语言,也是一个计算平台. Java 运行时版本 Java Runtime Edition 当你下载 Java 完时候,你会得到一个 Jav ...

  3. 【Java_基础】cmd下使用java命令运行class文件提示“错误:找不到或无法加载主类“的问题分析

    1.问题如下 当在命令行使用java命令执行字节码文件时提示“错误:找不到或无法加载主类” 2. 问题分析 这是由于在运行时类的全名应该是包名+类名,例如在包net.xsoftlab.baike下的类 ...

  4. java的运行机制(基础)

    1:高级语言的运行机制: 我们编程都是用的高级语言(写汇编和机器语言的大牛们除外),计算机不能直接理解高级语言,只能理解和运行机器语言,所以必须要把高级语言翻译成机器语言,计算机才能运行高级语言所编写 ...

  5. Java基础之Java编译运行过程

    Java编译运行过程 程序员所编写的是以.java为后缀的文件,此文件操作系统不能正确识别,因此,首先要经过编译,生成所谓的字节码文件(.class),而字节码文件需要JVM来提供运行环境的支持. J ...

  6. 关于JAVA,特点,历史,编译式的语言&解释式的语言,什么是java?JDK?DOS?一次编译到处运行原理。

    1.java语言的特点: 简单的:面向对象的:跨平台(操作系统)的(一次编译,到处运行):高性能的: 2.类名的首字母大写,方法小写: 3.历史: java2(即java),为什么加个2呢?1998年 ...

  7. JVM(二),Java怎样实现一次编译到处运行(平台无关性)

    二.Java怎样实现一次编译到处运行(平台无关性) 1.java平台无关性原理 Java源码首先被编译成字节码,再由不同平台的JVM进行解析,JAVA语言在不同的平台上运行时不需要进行重新编译,Jav ...

  8. 零基础怎么学Java?Java的运行机制是什么?Java入门基础!

    Java语言是当前流行的一种程序设计语言,因其安全性.平台无关性.性能优异等特点,受到广大编程爱好者的喜爱. 想学习Java语言的同学对于Java的运行机制是必须要了解的!! 计算机高级语言的类型主要 ...

  9. 02 基础 卸载JDK 安装JDK Java程序运行机制

    基础 JDK:Java Development Kit(Java开发者工具 包含JRE和JVM) JRE:Java Runtime Environment(java运行时环境,包含JVM) JVM:J ...

随机推荐

  1. Spark中的聚类算法

    Spark - Clustering 官方文档:https://spark.apache.org/docs/2.2.0/ml-clustering.html 这部分介绍MLlib中的聚类算法: 目录: ...

  2. 基于mockito做有效的单元测试

    概述 本文讲解的主要是有效和单元的思想,并不是说如何编写单元测试,用于改善和提高开发效率.编码风格.编码可读性和单测效率,不盲目追求覆盖率. 背景 现在很多单元测试只是利用@Test注解把代码或者整个 ...

  3. 1、了解JVM

    1.JVM.JRE.JDK JVM:是可以将要运行的程序编译成机器语言并去执行的一个平台,具有跨语言.跨平台的特性,运行时需要依赖JRE中的类库 JRE:包含了JVM以及代码运行时的类库,时Java程 ...

  4. Python-TypeError: object() takes no parameters

    Error: TypeError: object() takes no parameters Where? 使用自定义类的时候,实例类的时候传递参数,提示这个错误 Why? 因为类实例的时候,并不需要 ...

  5. Machine Learning-特征工程之特征选择

    特征工程之特征选择 目录 简介 1 Filter(过滤式选择) 1.1 移除低方差特征(variance threshold) 1.2 信息增益(information gain) 1.3 单变量特征 ...

  6. js undefined和null的判断

    function isUndef(value ){ return value === undefined || value === null; }

  7. MQTT消息队列压力测试

    环境准备: jmeter插件下载:mqttxmeter1.0.1jarwithdependencies.jar 把MQTT插件放在 %JMeter_Home%/lib/ext下.重启jmeter. M ...

  8. try with resource当中你没有注意到点。。

    怎么使用try with resource语法 在 JDK 9 中更简洁使用 try-with-resources 语句 try with resource当中你没有注意到点 try with res ...

  9. Java泛型的协变与逆变

    泛型擦除 Java的泛型本质上不是真正的泛型,而是利用了类型擦除(type erasure),比如下面的代码就会出现错误: 报的错误是:both methods  have same erasure ...

  10. 【基线检查】(高)基线检查--禁用local-infile选项(访问控制)

    (高)基线检查--禁用local-infile选项(访问控制) 描述 禁用local_infile选项会降低攻击者通过SQL注入漏洞器读取敏感文件的能力 检查提示 -- 加固建议 编辑Mysql配置文 ...