Chinaunix首页 | 论坛 | 博客
  • 博客访问: 52217
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 17
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-25 11:13
文章分类
文章存档

2016年(3)

2015年(6)

我的朋友

分类: Java

2015-12-11 15:32:35

第六章:jvm虚拟指令集
6.1假定:“必须”的含义
对于jvm指令的一些“必须”的要求,在运行期要求javaclass的结构是满足约束的,对于不满足约束的情况,jvm的行为是未定义的。
6.2保留操作码
在java class文件中使用的指令操作码,有三个操作码是保留的,供java虚拟机内部使用。
254(0xfe)和255(0xff),分别有助记符impdep1和impdep2,目的是在软件或者硬件实现的特定功能提供“后门”或陷阱。
202(0xca),有助记符breakpoint,目的是由调试程序使用来实现断点。

6.3虚拟机错误
当内部错误或者资源限制导致java语言语义不能实现时,jvm抛出一个VirtualMachineError类的子类的实例。jvm规范不规定和语言抛出的时间和地点。

6.4jvm指令集
我不一一例举各种指令的操作码和用法,需要时去查就行了。

第七章 为jvm编译
7.1范例格式
java编译成为class文件之后,以类汇编的jvm操作指令方式存在,jdk自带的javap程序具有这样的功能,将class文件翻译为这样的指令集。
下面是我测试的一个实例:
源文件为test.java
public class test {
    public static String a = "";
    public int i =0;
    public test() {
        int i=0;
        String a = "xyz";
    }

}
编译完成为test.class,用javap生成之后输出结果为:
C:\JBuilderX\jdk1.4\bin>javap -c  -classpath "c:/" test
Compiled from "test.java"
public class test extends java.lang.Object{
public static java.lang.String a;

public int i;

static {};
  Code:
   0:   ldc     #4; //String
   2:   putstatic       #5; //Field a:Ljava/lang/String;
   5:   nop
   6:   return

public test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   aload_0
   5:   iconst_0
   6:   putfield        #2; //Field i:I
   9:   iconst_0
   10:  istore_1
   11:  ldc     #3; //String xyz
   13:  astore_2
   14:  nop
   15:  return

}

7.2常数、局部变量和控制结构的使用
jvm是面向栈的,大多数操作都是从当前框架的操作数栈中取得操作数。

7。3运算
jvm一般在操作数栈上进行运算,即从栈中取操作数,并将结果存入操作数栈中。

7。4访问常数池
byte,char,short,以及小int值都可以通过立即数的方式编译在method的code中,但是int,long,float,double,以及string实例的引用,就需要对常数池进行访问了。使用ldc,ldc_w,ldc2_w指令管理。

7.5更多控制范例
可供查阅

7。6接收参数
如果向java实例方法传递了n个参数,它们被接收,按约定,框架的编号1到n的局部变量为新的方法调用创建,顺序为接收的顺序。
7。7调用方法
对java实例方法的调用,是在对象的运行期类型上调度的。用invokevirtual实现,将其参数取做对常数池表项的索引,给出对象的类类型的完整限定符名称,再调用方法的名称和方法的描述符。

对java静态(类)方法的调用,无需传递类实例,其余和实例方法相似,用invokespecial方法实现。

invokespecail指令用于调用实例初始化方法。超类方法和调用private方法。

7。8处理类实例
构建一个类实例的过程,在建立对象及其实例域之后,用invokespecial调用相应构造函数对应的方法来初始化对象。
对对象域的访问用getfield和putfield指令完成。

7。9数组
主要讲的是数组操作的相关jvm指令,如:newarray,过一遍,可以查阅。

7。10编译开关
对于java的switch指令,jvm有对应的两种指令:tableswitch,lookupswitch.
tableswitch指定取值范围,而lookupswitch并不指定取值范围,两者如何选择完全由效率选择决定。

7。11对操作数栈的操作
jvm有大量的指令补充,将操作数栈的内容作为无类型字或成对的无类型字操纵。便于jvm虚拟机指令的灵活组成。
如dup,dup_x2等,都是对字或者双字进行操作。

7。12抛出或者处理异常
jvm中try...catch块的处理对于jvm指令处理是透明的,辅助控制是由异常表来完成的,由异常表来决定到哪里去调用处理,哪些部分的异常是受控的。

7。13编译finally
try.....finally语句与try-catch相似,只是其辅助控制是由指令jsr(子例程调用)显式的表示,在jsr调用之前,将下一指令的地址压入栈中。而异常表只控制try块的范围。

7。14同步
jvm用monitorenter和monitorexit指令对同步提供显式支持。而java常用sychronized方法。
sychronized“方法”通常不是用monitorenter和monitorexit指令实现的。往往是由“方法调用指令”检查常数池里的ACC_SYCHRONIZED标志
但monitorenter和monitorexit指令是为了支持sychronized“语句”而存在的。
注意这里的方法和语句的区别。

语句实例如下:test.java
public class test {
  public test() {
  }
  public static void main(String[] args) {
    synchronized(new Object()){
        int i = 0;
    }
  }

}
编译完的结果:
C:\JBuilderX\bin>javap -c  -classpath "d:/epm40/classes" test
Compiled from "test.java"
public class test extends java.lang.Object{
public test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."":()V
   4:   nop
   5:   return

public static void main(java.lang.String[]);
  Code:
   0:   new     #2; //class Object
   3:   dup
   4:   invokespecial   #1; //Method java/lang/Object."":()V
   7:   dup
   8:   astore_1
   9:   monitorenter
   10:  iconst_0
   11:  istore_2
   12:  nop
   13:  aload_1
   14:  monitorexit
   15:  goto    23
   18:  astore_3
   19:  aload_1
   20:  monitorexit
   21:  aload_3
   22:  athrow
   23:  nop
   24:  return
  Exception table:
   from   to  target type
    10    15    18   any
    18    21    18   any

}

而synchronized方法编译没有特殊之处,只是在方法名上加了synchronzied字样。

 

From:http://www.blogjava.net/flyffa/archive/2006/08/24/65566.html

阅读(1291) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~