疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

java培训机构,java虚拟机的认识


 

 

 

  java的虚拟机制是java中重要的一个部分,也是java为什么能够有跨平台性的原因,那么java的虚拟机制到底是怎样的呢?java培训机构将为大家介绍。

  在C里面我们想执行一段自己编写的机器指令的方法大概如下:

  1. typedef void(*FUNC)(int);

  2. char* str = "your code";

  3. FUNC f = (FUNC)str;

  4. (*f)(0);

  也就是说,我们完全可以做一个工具,从一个文件中读入指令,然后将这些指令运行起来。上面代码中“编好的机器指令”当然指的是能在CPU上运行的,如果这里我还实现了一个翻译机器:从自己定义的格式指令翻译到CPU指令,那么就可以执行根据自定义格式的代码了。那么上面这段代码是不是相当于最简单的一个虚拟机了?下面来看JVM的总体结构:

ClassLoader的作用是装载能被JVM识别的指令(当然不只是从磁盘文件或内存去装载),那么我们先了解一下该格式:

  魔数以及版本就不说了(满大街的文件格式都是这个东西),接着的便是常量池,其中无非是两种东西:

  1. 字面常量(比如Integer、Long、String等);

  2. 符号引用(方法是哪里的?什么样的?);

  而我们知道,在JVM里面Class都是根据全限定名去找的,那么方法的描述当然也应该如此,那么就得到这些常量之间的关系如下:

  在接下来的“访问权限”中表明了该Class 是public还是private等,而this&super&interface则表面了“本类”、“继承自哪个类”、“实现了哪些接口”,实际上这里只是保存了代表这些信息的CONSTANT_Class_info的下标(u2)。

  感觉这里的NameIndex和 DescriptorIndex加起来和NameAndType有点像,那么为什么不直接用一个NameAndType的索引值表示?MethodInfo和FieldInfo之间最大的不同点就是Attributes。比如FieldInfo的属性表中存放的是变量的初始值,而 MethodInfo的属性表中存放的则是字节码。那么我们来依次看这些Attributes,首先是Code:

 

  有几个有意思的地方:

  1. 从Class文件中可以知道在执行的过程中栈的深度;

  2. 对于非静态方法,编译器会将this通过参数传递给方法;

  3. 异常表中记录的范围是指令的行数(而不是源代码的);

  4. 这里的异常是指try-catch中的,而与Code同级的异常表中的则是指throws出去的;

  Exceptions则非常简单:

  LineNumberTable保存了字节码和源码之间的关系,结构如下:

 

LocalVariableTable描述了栈帧中局部变量表的变量和源代码中定义的变量之间的关系,结构如下: