Tomcat指定native library路径

一般,指定JVM的native library路径,只需要用下面的参数就好了

-Djava.library.path=PATH_TO_NATIVE_LIBRARY

Tomcat指定native library路径时,还是不要使用这边参数的好。
建议直接修改PATH环境变量,将dll或so放到环境变量PATH的路径下就好了。
TOMCAT默认将PATH赋值给-Djava.library.path参数的。

JNI简单例子2

最近又用jni写了一个编码工具,从中抽出了最简单的代码,如下:

1、Compress4j.java

package com.neohope.test.compress.jni;

/**
 *
 * @author Hansen
 */
public class Compress4j {
    private native int encodeR(String inFilePath,String outFilePaht);
    private native int decodeR(String inFilePath,String outFilePaht);
    
    static{
        try{
            System.loadLibrary("compress4j");
        }catch(UnsatisfiedLinkError e){
            //nothing to do
            System.out.println("Error: Couldn't load compress4j");
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
    
    public String encode(String inFilePath,String outFilePath)
    {
        encodeR(inFilePath, outFilePath);
        return "xxxxx";
    }
    
    public String decode(String inFilePath,String outFilePath)
    {
        decodeR(inFilePath, outFilePath);
        return "xxxxx";
    }
}

2、找到生成的classes文件夹,运行命令行:

javah -classpath . -jni com.neohope.test.compress.jni.Compress4j 

3、生成的.h文件如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_neohoe_test_compress_jni_Compress4j */

#ifndef _Included_com_neohoe_test_compress_jni_Compress4j
#define _Included_com_neohoe_test_compress_jni_Compress4j
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_neohoe_test_compress_jni_Compress4j
 * Method:    encodeR
 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_neohoe_test_compress_jni_Compress4j_encodeR
  (JNIEnv *, jobject, jstring, jstring);

/*
 * Class:     com_neohoe_test_compress_jni_Compress4j
 * Method:    decodeR
 * Signature: (Ljava/lang/String;Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_neohoe_test_compress_jni_Compress4j_decodeR
  (JNIEnv *, jobject, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif

3、编写成的.cc文件如下

#include "com_neohoe_test_compress_jni_Compress4j.h"

JNIEXPORT jint JNICALL Java_com_neohoe_test_compress_jni_Compress4j_encodeR
  (JNIEnv *env, jobject, jstring inpathjs, jstring outpathjs)
{
    //first convert jstring to const char*
    const char* inpath = env->GetStringUTFChars( inpathjs, false);
    const char* outpath = env->GetStringUTFChars( outpathjs, false);

    //...

    return 0;
}

JNIEXPORT jint JNICALL Java_com_neohoe_test_compress_jni_Compress4j_decodeR
  (JNIEnv *env, jobject, jstring inpathjs, jstring outpathjs)
{
    //first convert jstring to const char*
    const char* inpath = env->GetStringUTFChars( inpathjs, false);
    const char* outpath = env->GetStringUTFChars( outpathjs, false);

    //...

    return 0;
}

4、在VS工程中,新增头文件目录
%JAVA_HOME%/include
%JAVA_HOME%/include/win32

5、编译为dll即可使用啦

6、关于mt和md的问题
编译为MT和MTd的话,用JNI是没有任何问题的
编译为MD的话,需要安装VC2010sp1可再发行包
编译为MDd的话,就比较麻烦了,手动复制依赖的dll后,我用c++调用dll可以成功,但用jni就一直提示:缺少依赖的dll

JNI简单例子1

1.Java代码CallApi.java

class CallApi{
    private native String showMessageBox(String msg);
    private native double getRandomDouble();

    static{
        try{
            System.loadLibrary("CallApi");
            System.out.println("Loaded CallApi");
        }catch(UnsatisfiedLinkError e){
            //nothing to do
            System.out.println("Couldn't load CallApi");
            System.out.println(e.getMessage());
        }
    }

    public static void main(String args[]){
        CallApi api = new CallApi();
        double randomNumber = api.getRandomDouble();
        String retval = api.showMessageBox("Hello from Java!\n"+
            "The native random number: "+randomNumber);
            System.out.println("The native string: "+retval);
    }
}

2.生成dll的CallApi.h文件

javah -classpath . -jni CallApi
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CallApi */

#ifndef _Included_CallApi
#define _Included_CallApi
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CallApi
 * Method:    showMessageBox
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox
  (JNIEnv *, jobject, jstring);

/*
 * Class:     CallApi
 * Method:    getRandomDouble
 * Signature: ()D
 */
JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

3.手写dll的CallApi.c文件

#include"CallApi.h"
#include <windows.h>
#include <time.h>

//#pragma comment(lib,"user32.lib")

JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox
  (JNIEnv *env, jobject thisObject, jstring js)
{
    //first convert jstring to const char for use in MessageBox
    const jbyte* argvv = (*env)->GetStringUTFChars(env, js, NULL);
    char* argv =(char *) argvv;

    //Call MessageBoxA
    MessageBox(NULL, argv, "Called from Java!", MB_ICONEXCLAMATION | MB_OK);
    return js;

}


JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble
  (JNIEnv *env, jobject thisObject)
{
    double num1;
    srand((unsigned)(time(0)));
    num1 = ((double)rand()/(double)RAND_MAX);

    return num1;
}

4.编译
注意1:要引用jdk下的include目录下文件,因此要增加引用文件路径
注意2:用MT而不是MD

5.运行

java -Djava.library.path=. CallApi