Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\user\GCMDLN.DLL: Can't load IA 32-bit .dll on a AMD 64-bit platform
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at acm.util.DOSCommandLine.getCommandLine(JTFTools.java:1622)
at acm.util.JTFTools.getCommandLine(JTFTools.java:439)
at acm.util.JTFTools.getMainClass(JTFTools.java:464)
at acm.program.Program.main(Program.java:1320)
原因是ACM Java Task Force库不鼓励用户自己写main方法,在acm.program.Program和acm.program.CommandLineProgram的main方法中通过猜测方式获取实际要执行的类,main中用到的acm.util.DOSCommandLine里包含的GCMDLN.DLL是32位的(转为字符串形式存在代码中并在需要时解到user.home目录),需要做64位DLL来实现getLine方法。
先用javah生成头文件
javah -d . -classpath acm.jar acm.util.DOSCommandLine
比较了一下,32位和64位JRE生成的头文件是一样的。
再根据头文件写代码
从对返回值的使用上来看,直接获取调java时的命令行即可。
JNIEXPORT jstring JNICALL Java_acm_util_DOSCommandLine_getLine(JNIEnv *env, jclass cl)
{
LPWSTR s = GetCommandLineW();
return (*env)->NewString(env, s, lstrlenW(s));
}
用tcc编译
tcc -I"C:\Program Files\Java\jdk1.8.0\include" -I"C:\Program Files\Java\jdk1.8.0\include\win32" -shared -o GCMDLN.DLL.DLL acm_util_DOSCommandLine.c
放在System32下就可以了。
为什么输出成GCMDLN.DLL.DLL?
因为acm.util.DOSCommandLine里写的是System.loadLibrary("GCMDLN.DLL"),库名带了后缀,以前的JRE这么写可能没问题,现在不行了。现在的32位JRE里跑jtf库也会报错:
Exception in thread "main" java.lang.UnsatisfiedLinkError: acm.util.DOSCommandLine.getLine()Ljava/lang/String;
at acm.util.DOSCommandLine.getLine(Native Method)
at acm.util.DOSCommandLine.getCommandLine(JTFTools.java:1627)
at acm.util.JTFTools.getCommandLine(JTFTools.java:439)
at acm.util.JTFTools.getMainClass(JTFTools.java:464)
at acm.program.Program.main(Program.java:1320)
于是也做了32位的DLL放在SysWOW64下,这样就不用考虑JRE位数了。
代码和DLL放在了My Shared Folder里的jtf-GCMDLN.zip。
不用DLL的解决方法:
- 打成jar在minifest里指定类名;
- 自己写main方法;
- 在命令行加上“code=类名或class文件路径”的参数指定类名。
没有评论:
发表评论