这几天忙着写一个用于数据同步的Java程序,在这里遇到了一个令人头大的问题。
问题是这样:我的数据同步程序要同时跑四个线程,在其中的一个线程中,要做一个MD5的文件校验工作。这个MD5的校验是要通过调用一个dll来实现,这个dll(名字叫做MD5Operation.dll)是用于对文件内容进行MD5运算的,目的是用于做服务器端和客户端的文件校验。
类MD5Tool的源代码如下:
package com.hode.util;
public class MD5Tool
{
public static native String hMd5( String szFilePath);
static
{
System.loadLibrary( "MD5Operation" );
}
}
我声明了一个静态的本地方法hMD5,这样我在程序中就可以直接用MD5Tool.hMD5(filePathName)来调用了,经过我的简单测试,程序运行正常。
测试代码如下:
package com.hode.util
public class TestMD5
{
public static void main(String[] args)
{
String filePathName = "C://my music//heal the world.mp3";
String fileMD5Str = MD5Tool.hMD5(filePathName);
System.out.println("fileMD5Str=" + fileMD5Str);
}
}
但是当我把它拿到数据同步的程序中运行,当程序运行到MD5Tool.hMD5(filePathName)这条语句的时候,莫名其妙的终止了,而且不会抛出任何异常,这实在让人看不懂。找了半天的原因,也找不出什么问题,因为毕竟调用MD5的代码就那么几行,把它翻来覆去折腾几遍还是那个样子。我真的有点搞不定了,这时Neil拿来一本《 JAVA线程 》,他找到一页关于调用native方法的相关问题,书中说道,在多线程的环境中,调用native方法时,要声明成synchronized static的,否则会出现问题而导致线程终止。嘿嘿!有点意思了,我赶忙将代码改了过来,我的代码变成了:
package com.hode.util;
public class MD5Tool
{
public synchronized static native String hMd5( String szFilePath);
static
{
System.loadLibrary( "MD5Operation" );
}
}
再次运行,结果让人失望,程序仍然会终止!到底问题出在哪里??我有点灰心了... ...
既然《JAVA 线程》中已经说明了,在多线程的环境下调用native方法可能会出问题,那么是不是因为在子线程中加载dll的时候会有问题呢?不试不知道,一试吓一跳,我把dll的加载放到了主线程中,然后在子线程中进行调用,代码简略如下:
package com.hode.sync.thread;
import com.hode.util.MD5Tool;
public class MainThread extends Thread
{
private MD5Tool myMD5Tool = new MD5Tool(); //在主线程中加载dll
.... .... ....
public static void main(String[] args)
{
.... .... ....
SubThread1 T1 = new SubThread1();
SubThread1.run();
.... .... ....
}
}
public class SubThread1 extends Thread
{
public void run()
{
.... .... ....
String filePathName = "C://my music//heal the world.mp3";
String fileMD5Str = MD5Tool.hMD5(filePathName); //在子线程中调用hMD5方法
System.out.println("fileMD5Str=" + fileMD5Str);
.... .... ....
}
}
运行成功啦!哦,原来是这样,在调用native方法的时候要注意以下几点:
(1) 在多线程的同时运行的时候,最好将native方法声明成synchronized static。
(2) dll的加载要在主线程中进行,但可以在子线程中调用。