月度归档:2011年03月

JNA实例

有时候Java需要通过调用dll来操作底层的硬件或者现有的组件,直接使用JNI是容易出错的,且需要编写本地的C代码。这里介绍另一个调用dll的更简单的方法:JNA。这里介绍JNA调用dll的本地方法、JNA回调Java方法以及JNA相关的一些知识点。如果去留意的话,会发现现在很多jar包都用JNA来调用dll了。

继续阅读

同步方法与同步代码块的区别

当JVM执行一个方法时,执行中的线程识别该方法的 method_info 结构是否有 ACC_SYNCHRONIZED 标记设置,然后它自动获取对象的锁,调用方法,最后释放锁。如果有异常发生,线程自动释放锁。

同步化一个方法块会超过JVM对获取对象锁和异常处理的内置支持,要求以字节代码显式写入功能。如果使用同步方法读取一个方法的字节代码,就会看到有十几个额外的操作用于管理这个功能。

public class Sync {
    private int i;

    public synchronized int synchronizedMethodGet() {
        return i;
    }

    public int synchronizedBlockGet() {
        synchronized( this ) {
            return i;
        }
    }

}

反编译出的字节码:

D:\Java\jdk1.6.0_02\bin>javap -c Sync
Compiled from "Sync.java"

public class Sync extends java.lang.Object{
public Sync();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public synchronized int synchronizedMethodGet();
  Code:
   0:   aload_0
   1:   getfield        #2; //Field i:I
   4:   ireturn

public int synchronizedBlockGet();
  Code:
   0:   aload_0
   1:   dup
   2:   astore_1
   3:   monitorenter
   4:   aload_0
   5:   getfield        #2; //Field i:I
   8:   aload_1
   9:   monitorexit
   10:  ireturn
   11:  astore_2
   12:  aload_1
   13:  monitorexit
   14:  aload_2
   15:  athrow
  Exception table:
   from   to  target type
     4    10    11   any
    11    14    11   any

}

finally语句的执行时刻

以前虽然知道在try finally语句中,即使try块里有return语句,finally语句也会在return语句执行之前执行,却不知道return表达式与finally语句的执行顺序。

public class Test {
    public static int a() {
        int i = 0;

        try {
            i++;
            return ++i;

        } finally {
            i++;
        }
    }

    public static void main(String[] args) {
        System.out.println(a());
    }
}

这个语句的输出是 2 而不是 3
当执行到 return ++i;

jvm是先执行 ++i,把结果 2 存到临时变量,然后在执行finally语句里的 ++i,所以最终的i的值虽然是 i,但方法返回的值却是 2

其实以前的理解没有错,因为 return ++i; 是一个复合语句了,相当于:

    int j = ++i;  
    return j;