JVM虚拟机

来源:互联网 发布:打开23端口 编辑:程序博客网 时间:2024/06/15 20:59

Java字节码是执行在JRE上的,JRE中最重要的部分是Java虚拟机,JVM负责分析和执行Java字节码。本博客hi阐述JVM是如何运行的,包括它的结构,它如何去执行字节码,以及按照怎样的顺序去执行,也会给出一些常见的错误的示例以及对应的解决方法

虚拟机
JRE是由Java API和JVM组成的。JVM的主要作用是通过Class Loader来加载Java程序,并且按照Java API来执行加载的程序。
虚拟机是通过软件的方式来模拟实现的机器(比如说计算机),它可以像物理机一样执行程序。设计虚拟机的初衷是让Java能够通过它来实现WORA(write once run anywhere 一次编译,到处运行)。因此,JVM可以在不修改Java代码的情况下,在所有的硬件环境上运行Java字节码。

Java虚拟机的特点如下:

基于栈的虚拟机:Intel x86和ARM这两种最常见的计算机体系的机构都是基于寄存器的。不同的是,JVM是基于栈的。
符号引用:除了基本类型以外的数据(类和接口)都是通过符号来引用,而不是通过显式地使用内存地址来引用。
垃圾回收机制:类的实例都是通过用户代码进行创建,并且自动被垃圾回收机制进行回收。
通过对基本类型的清晰定义来保证平台独立性:传统的编程语言,例如C/C++,int类型的大小取决于不同的平台。JVM通过对基本类型的清晰定义来保证它的兼容性以及平台独立性。
网络字节码顺序:Java class文件用网络字节码顺序来进行存储:为了保证和小端的Intel x86架构以及大端的RISC系列的架构保持无关性,JVM使用用于网络传输的网络字节顺序,也就是大端。

Java字节码(Java bytecode)
为了保证WORA,JVM使用Java字节码这种介于Java和机器语言之间的中间语言,字节码是部署Java代码的最小单位。
现象:一个一直运行正常的应用突然无法运行了,在类库被更新之后,返回如下的错误
这里写图片描述

这里写图片描述

简而言之,之前没有返回值的addUser()被修改为返回一个User类的实例的方法。不过,应用的代码没有做任何的修改,因为它没有使用addUser()的返回值。com.nhnuser.UserAdmin.addUser()方法似乎依然存在,如果存在的话,那么怎么还会出现NoSuchMethodError的错误呢?

原因:上面问题的原因是在于应用的代码没有用新的类库来进行编译,换句话说,应用代码似乎调用了正确的方法,只是没有使用它的返回值而容易。不过如何,编译后的class文件表明这个方法是有返回值的。

NoSuchMethodError出现的原因是“com.nhn.user.UserAdmin.addUser(Ljava/lang/String;)V”方法找不到。注意一下”Ljava/lang/String;”和最后面的“V”。在Java字节码的表达式里,”L;”表示的是类的实例。这里表示addUser()方法有一个java/lang/String的对象作为参数。在这个类库里,参数没有被改变,所以它是正常的。最后面的“V”表示这个方法的返回值。在Java字节码的表达式里,”V”表示没有返回值(Void)。综上所述,上面的错误信息是表示有一个java.lang.String类型的参数,并且没有返回值的com.nhn.user.UserAdmin.addUser方法没有找到。

因为应用是用之前的类库编译的,所以返回值为空的方法被调用了。但是在修改后的类库里,返回值为空的方法不存在,并且添加了一个返回值为“Lcom/nhn/user/User”的方法。因此,就出现了NoSuchMethodError。

注:

这个错误出现的原因是因为开发者没有用新的类库来重新编译应用。不过,出现这种问题的大部分责任在于类库的提供者。这个public的方法本来没有返回值的,但是后来却被修改成返回User类的实例。很明显,方法的签名被修改了,这也表明了这个类库的后向兼容性被破坏了。因此,这个类库的提供者应该告知使用者这个方法已经被改变了。

参考博客:http://blog.csdn.net/zhoudaxia/article/details/26454421/(重点博客)

原创粉丝点击