Loading

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");
    }
}

 

posted @ 2018-01-06 10:32  stono  阅读(526)  评论(0编辑  收藏  举报