去年也大概是這個(gè)時(shí)候?qū)懥说谝粋€(gè)Java2EXE,之后又加了寫(xiě)特性,但是每次我看代碼都感覺(jué)慘不忍睹,很混亂,而且編譯,鏈接的過(guò)程也有點(diǎn)繞。
現(xiàn)在又過(guò)了一年了,如果說(shuō)上次版本的Load過(guò)程主要是靠Java(Java加密,解壓),那么這次基本把這些費(fèi)時(shí)的操作全交給CPP了。
好了,總結(jié)一下這次的改動(dòng)
1)Loader以及Starter完全是CPP代碼,結(jié)構(gòu)很清晰了。
2)加密以及解壓交給CPP,速度比以前快了。
3)整合了
JNative,這個(gè)是重點(diǎn),下文詳述。
4)生成工具用MFC寫(xiě),一個(gè)簡(jiǎn)單的向?qū)А?br />
OK,那么JNative是干什么的呢?
官方的描述是 “
JNative, Java framework for DLL access for Windows and Linux”
就是說(shuō),有了這個(gè)框架,你訪(fǎng)問(wèn)DLL里的方法就不再需要寫(xiě)DLL了,只需要寫(xiě)Java Code了,可能有人問(wèn)它是怎么做到的呢?
假如說(shuō)你要訪(fǎng)問(wèn)Kernel32.dll里的某個(gè)方法A,你首先需要這個(gè)方法的句柄,這個(gè)句柄就是通過(guò)new一個(gè)org.xvolks.jnative.JNative實(shí)例來(lái)保持的,
類(lèi)似如:
org.xvolks.jnative.Native methodA=new org.xvolks.jnative.JNative("Kernel32.dll","A");
有了這個(gè)句柄,你只要在上面設(shè)置參數(shù),返回值,以及類(lèi)型就可以調(diào)用它了。每個(gè)調(diào)用它上面的JNI里的本地方法就會(huì)自動(dòng)來(lái)進(jìn)行參數(shù)解析,解碼,調(diào)用到目標(biāo)DLL方法,這個(gè)過(guò)程基本不可避免需要少量的匯編代碼。
JNative為了可移植性,代碼是在Cygwin下可編譯的,沒(méi)有MSVC可編譯的版本。
對(duì)此,本人改了部分代碼用于直接一起鏈接(主要是把GCC嵌入?yún)R編改為對(duì)應(yīng)的MSVC的嵌入?yún)R編代碼),而不是讓JNative生成一個(gè)動(dòng)態(tài)鏈接庫(kù)。
如上,由于JNative改成了靜態(tài)庫(kù),程序發(fā)布的時(shí)候,只要是通過(guò)Java2EXE Builder來(lái)創(chuàng)建成EXE的話(huà),你就不需要那個(gè)JNativeCpp.dll文件了,只有一個(gè)EXE.
你調(diào)試的時(shí)候可以用官方的版本,發(fā)布就只要你的代碼(JNative的class也都在集成在生成工具里,不需要你自己添加進(jìn)來(lái))。
來(lái)看個(gè)簡(jiǎn)單的例子,我們從Java代碼里取得當(dāng)前進(jìn)程的全路徑名:
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.Type;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.pointers.Pointer;
import org.xvolks.jnative.pointers.memory.HeapMemoryBlock;
/**
* DWORD GetModuleFileName(
* HMODULE hModule,
* LPTSTR lpFilename,
* DWORD nSize
*);
* @author yovn
*
*/
public class TestReadProcessPath {
/**
*
* @param args
* @throws NativeException
* @throws IllegalAccessException
*/
public static void main(String[] args) throws NativeException, IllegalAccessException {
JNative v=new JNative("Kernel32.dll","GetModuleFileNameA");
int i = 0;
v.setRetVal(Type.INT);
Pointer pName = new Pointer(new HeapMemoryBlock(1024));
v.setParameter(i++, 0);//module handle
v.setParameter(i++, pName);//pFileName
v.setParameter(i++, 1024);//nSize
v.setRetVal(Type.INT);
v.invoke();
int ret = Integer.parseInt(v.getRetVal());
if (ret == 0) {
// return "null";
System.err.println(
"GetModuleFileName failed!");
} else {
String path = pName.getAsString().substring(0,
ret);
pName.dispose();
v.dispose();
System.out.println("current process's path is:"+path);
}
}
}
編譯,把這個(gè)文件單獨(dú)打包成一個(gè)jar文件,下面是個(gè)用這個(gè)工具生成EXE的截圖:
生成EXE向?qū)У谝徊?/a>
生成 EXE向?qū)У诙?/a>
請(qǐng)從這里下載 Java2EXE Builder Platform