JAVA platform=JRE=JVM标准实现+java核心类库,是java程序的运行程序,没有编译器和调试器。
JDR =JRE+ 编译工具。
已经编译好的java程序只需要jre既可以运行,不需要JDK。
开发java程序,需要jdk编译。
写好的程序是java,经过编译,识别出那部分是类,那部分是变量,然后用class文件存储起来。
之所以叫 java虚拟机,是通过虚拟化的方式,是操作系统层透明,不需要考虑操作系统平台,只要有jvm都可以运行。
JVM提供了class文件到操作系统的联系,是一种标准,不同的厂商都可以使用不同的方法。
JVM 只能运行class文件,是二进制码。

Class文件结构如下。
U1表示一个字节,U2表示两个字节,U4表示四个字节。

java文件夹下所有文件 合并到一个文件 java文件组成_JVM


拿helloworld为例子。

java文件夹下所有文件 合并到一个文件 java文件组成_java_02


class文件如下。

java文件夹下所有文件 合并到一个文件 java文件组成_十进制_03


按照class文件结构,第一个是4个字节的magic。

一个字节是8位,一个16进制表示4位,所有用8个16进制来表示这4个字节的magic。

也就是CA FE BA BE。

Magic是用来给不同的文件分类的,CA FE BA BE表示这是一个java的class文件,用来做校验。

如果这个magic不对,在JVM运行class文件是,会赞侧到文件类型不正确,执行时会报错。比如手动更改该值,会得到以下报错。

java文件夹下所有文件 合并到一个文件 java文件组成_JVM_04


再往下看是2个字节的minor version, 2个字节的major version.

该例子里是, minor version 00 00 转换十进制为0, major version 00 34转换十进制为52.

major version是从45 开始数的, 45 对应java1, 46对应 2,,,52 对应java8 .

也就是说这个程序最低要放在 java 8.0上运行。

这是由于用高版本jdk编译的程序,可能会用到一些高版本里才有的包和功能,在低版本的jvm上无法运行,这样编译时会把版本写进去,在jvm运行的时候检查。

如果不符合版本要求会抛出“Unsupported major.minor version 52.0” 这样的报错。

再往后是2个字节常量池,用来存一些文本字符串,八种基本类型的值,和被生命为final的常量。

再往后开始各种entry,需要知道各种entry对应的结构体,以及tag。

type tag
 utf 8 1
 integer 3
 float 4
 double 6
 class 7
 string 8
 Fieldref 9
 methodref 10
 interfacementhodref 11
 nameand type 12

以这个例子为例,接下来往后读发现是07, 对应是一个class。

Constant_class_infor{
 u1 tag;
 u2 name.index
 }


一个字节的tag,一个字节8 为,用2 个18进制表示,正好是07.
两个字节的名字索引,也就是后面的 00 02 表示名字索引,也就是说这个class的名字存在0002 的索引里。于是去读 0002 的位置,也刚好是下一位 01.。01 表示Utf8

Constant_utf8_infor{
 u1 tag;
 u2 length;
 u1 byte【length】;
 }


1个字节tag,2个字节的长度,再加上长度字节的数组。
01 是tag,00 28 是长度,是6进制0028 对应 十进制的40字节,后面40字节都是用来存这个类的名字的。
由于长度只能用两个字节表示,16位, 最大65535 =64kb, 所以定义需要用utf8表示的,长度不可以超过65535.
后边其他也是同样的方法,值得一提的是 this。

java文件夹下所有文件 合并到一个文件 java文件组成_十进制_05


this 的index指回0001, 通过这种方法返回this.最后,javap命令可以帮助分析。

java文件夹下所有文件 合并到一个文件 java文件组成_JVM_06