java中native的用法
java中native的用法
public static native void java.lang.System.arraycopy(Object, int, Object, int, int)方法竟然是native的,
查询了一下java中native的用法,找到如下文章,
学习了:https://www.cnblogs.com/b3051/p/7484501.html
但是,自己手痒,写了一下,结果,填了几个坑;
1,javah 之前没有使用过,用起来还算可以,中规中矩;
2,编写C文件也还可以;随便写,结果就挖了一个坑;
3,使用cl编译有些问题,有些文章说要安装Visio Studio 20XX,
学习了:http://blog.163.com/yuyang_tech/blog/static/2160500832013118112049372/
决定使用vc6.0来做,
下载地址:http://www.pc6.com/softview/SoftView_51072.html
解压至D:\pvc6\VC98\BIN,在添加到系统path中;
后来发现我把D:\pvc6\COMMON\MSDEV98\BIN;D:\pvc6\VC98\INCLUDE也加到路径里面了;忘记为啥了;
出错1:
D:\Java\gitworkspace\Coding\bin>CL.EXE -I%java_home%\include -I%java_home%\inclu de\win32 -LD JavaNativeImp.c -Fehello.dll Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved. JavaNativeImp.c D:\Java\jdk1.8.0_05\include\jni.h(39) : fatal error C1083: Cannot open include f ile: 'stdio.h': No such file or directory
开始模拟 -I参数,
CL.EXE -I%java_home%\include -I%java_home%\include\win32 -ID:\pvc6\VC98\INCLUDE -LD JavaNativeImp.c -Fehello.dll
出错2:
D:\Java\gitworkspace\Coding\bin>CL.EXE -I%java_home%\include -I%java_home%\inclu de\win32 -ID:\pvc6\VC98\INCLUDE -LD JavaNativeImp.c -Fehello.dll Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved. JavaNativeImp.c Microsoft (R) Incremental Linker Version 6.00.8168 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. /dll /implib:hello.lib /out:hello.dll JavaNativeImp.obj LINK : fatal error LNK1104: cannot open file "LIBCMT.lib"
找不到参数可以加lib了,
学习了:http://blog.csdn.net/cruise_h/article/details/29218407
在我的电脑->属性->高级系统设置->环境变量->系统变量中新建系统变量LIB、INCLUDE并设置它们的值为:
LIB:D:\pvc6\VC98\LIB
INCLUDE:%java_home%\include;%java_home%\include\win32;D:\pvc6\VC98\INCLUDE
这样直接输入:cl -LD JavaNativeImp.c -Fehello.dll就可以编译了;
输出:
D:\Java\gitworkspace\Coding\bin>cl -LD JavaNativeImp.c -Fehello.dll Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8168 for 80x86 Copyright (C) Microsoft Corp 1984-1998. All rights reserved. JavaNativeImp.c Microsoft (R) Incremental Linker Version 6.00.8168 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. /dll /implib:hello.lib /out:hello.dll JavaNativeImp.obj Creating library hello.lib and object hello.exp
结果运行的时候报错;
出错3:
D:\Java\gitworkspace\Coding\bin>java com.stono.jvm.JavaNative Exception in thread "main" java.lang.UnsatisfiedLinkError: D:\Java\gitworkspace\ Coding\bin\hello.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.loadLibrary0(Unknown Source) at java.lang.System.loadLibrary(Unknown Source) at com.stono.jvm.JavaNative.<clinit>(JavaNative.java:6)
因为在Eclipse中使用了64位的java,dll使用的是32位的;
学习了:https://stackoverflow.com/questions/8113080/cant-load-ia-32-bit-dll-on-a-amd-64-bit-platform 只能把Java改成32位了;因为C语言64不熟悉;
重新用EditPlus写了Java文件,用32位jdk编译;
运行的时候报错,
出错4:
D:\>d:\java\jdk1.6.0_12\bin\java.exe JavaNative Exception in thread "main" java.lang.UnsatisfiedLinkError: JavaNative.hello(Ljav a/lang/String;)V at JavaNative.hello(Native Method) at JavaNative.main(JavaNative.java:7)
最开始以为是dll文件是原来的java程序生成的,就又重头跑了一遍;就是先javah -jni xxx,然后写c文件,然后cl编译;
结果还是出错4;
学习了:https://www.cnblogs.com/cuglkb/p/5665882.html 这个方法没有测试;
http://blog.csdn.net/missingu1314/article/details/12650725 用的是这个方法;
主要是因为在dll中,可能xxx.h头文件中的接口名和xxx.cpp源文件中的实现函数名不一致导致的。
源码:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class JavaNative */ #ifndef _Included_JavaNative #define _Included_JavaNative #ifdef __cplusplus extern "C" { #endif /* * Class: JavaNative * Method: hello * Signature: (Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_JavaNative_hello (JNIEnv *, jobject, jstring); #ifdef __cplusplus } #endif #endif
#include <jni.h> #include "JavaNative.h" #include <stdio.h> JNIEXPORT void JNICALL Java_JavaNative_hello(JNIEnv *env,jobject obj, jstring name){ const char *str; str = (*env)->GetStringUTFChars(env, name, NULL); if (str == NULL) { return; } printf("Hello World! %s \n", str ); return; }
C文件可以随便起名,但是方法必须和接口中的名字一样;
然后就又是cl编译,然后java JavaNative就可以了;
Java源码:
public class JavaNative { public native void hello(String name); static{ System.loadLibrary("hello"); } public static void main(String[] args) { new JavaNative().hello("jni"); } }