• 关于JNI程序中引用另外一个lib


    我最近在写一个j2se的程序,我用的是开源的org.amse.ys.zip包里的代码,这部分代码是在FBReaderJ里抽取的,但是其中包含了一些native的方法,需要用的zlib库,而FBReaderJ由于是运行在Android平台上的,它对应的so库肯定是无法在我的程序中使用,因此,在这里下载了zlib的win32运行库后,我使用 

    1 javah -jni org.amse.ys.zip.DeflatingDecompressor

    生成了org_amse_ys_zip_DeflatingDecompressor.h 头文件,内容如下:

     1 /* DO NOT EDIT THIS FILE - it is machine generated */
     2 #include "jni.h"
     3 /* Header for class org_amse_ys_zip_DeflatingDecompressor */
     4 
     5 #ifndef _Included_org_amse_ys_zip_DeflatingDecompressor
     6 #define _Included_org_amse_ys_zip_DeflatingDecompressor
     7 #ifdef __cplusplus
     8 extern "C" {
     9 #endif
    10 #undef org_amse_ys_zip_DeflatingDecompressor_IN_BUFFER_SIZE
    11 #define org_amse_ys_zip_DeflatingDecompressor_IN_BUFFER_SIZE 2048L
    12 #undef org_amse_ys_zip_DeflatingDecompressor_OUT_BUFFER_SIZE
    13 #define org_amse_ys_zip_DeflatingDecompressor_OUT_BUFFER_SIZE 32768L
    14 /*
    15  * Class:     org_amse_ys_zip_DeflatingDecompressor
    16  * Method:    startInflating
    17  * Signature: ()I
    18  */
    19 JNIEXPORT jint JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_startInflating
    20   (JNIEnv *, jobject);
    21 
    22 /*
    23  * Class:     org_amse_ys_zip_DeflatingDecompressor
    24  * Method:    endInflating
    25  * Signature: (I)V
    26  */
    27 JNIEXPORT void JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_endInflating
    28   (JNIEnv *, jobject, jint);
    29 
    30 /*
    31  * Class:     org_amse_ys_zip_DeflatingDecompressor
    32  * Method:    inflate
    33  * Signature: (I[BII[B)J
    34  */
    35 JNIEXPORT jlong JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_inflate
    36   (JNIEnv *, jobject, jint, jbyteArray, jint, jint, jbyteArray);
    37 
    38 #ifdef __cplusplus
    39 }
    40 #endif
    41 #endif

    建立VS2005 DLL工程,加入jni.h, jni_md.h, zlib的 zconf.h, 加入zdll.lib依赖,加入DeflatingDecompressor.cpp:

     1 /*
     2  * Copyright (C) 2009-2013 Geometer Plus <contact@geometerplus.com>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    17  * 02110-1301, USA.
    18  */
    19 #include <string.h>
    20 #include "zlib.h"
    21 
    22 #include <new>
    23 #include "jni.h"
    24 #include "org_amse_ys_zip_DeflatingDecompressor.h"
    25 
    26 #define                                SIZE                            10
    27 
    28 static z_stream*            ourStreams[SIZE]            = { 0 };
    29 
    30 extern "C"
    31 JNIEXPORT jint JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_startInflating(JNIEnv *env, jobject thiz) {
    32     int i;
    33     for (i = 0; i < SIZE; ++i) {
    34         if (ourStreams[i] == 0) {
    35             ourStreams[i] = new z_stream;
    36             memset(ourStreams[i], 0, sizeof(z_stream));
    37             inflateInit2(ourStreams[i], -MAX_WBITS);
    38             return i;
    39         }
    40     }
    41     return -1;
    42 }
    43 
    44 extern "C"
    45 JNIEXPORT void JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_endInflating(JNIEnv *env, jobject thiz, jint inflatorId) {
    46     if (inflatorId >= 0 && inflatorId < SIZE) {
    47         inflateEnd(ourStreams[inflatorId]);
    48         delete ourStreams[inflatorId];
    49         ourStreams[inflatorId] = 0;
    50     }
    51 }
    52 
    53 // returns (endFlag << 32) + ((used inLength) << 16) + outLength
    54 extern "C"
    55 JNIEXPORT jlong JNICALL Java_org_amse_ys_zip_DeflatingDecompressor_inflate(JNIEnv *env, jobject thiz, jint inflatorId, jbyteArray in, jint inOffset, jint inLength, jbyteArray out) {
    56     if (inflatorId < 0 || inflatorId >= SIZE) {
    57         return -1;
    58     }
    59     z_stream *stream = ourStreams[inflatorId];
    60     if (stream == 0) {
    61         return -2;
    62     }
    63 
    64     jbyte* inStart = env->GetByteArrayElements(in, 0);
    65     jbyte* outStart = env->GetByteArrayElements(out, 0);
    66     stream->next_in = (Bytef*)inStart + inOffset;
    67     stream->avail_in = inLength;
    68     stream->next_out = (Bytef*)outStart;
    69     const int outLength = env->GetArrayLength(out);
    70     stream->avail_out = outLength;
    71     const int code = inflate(stream, Z_SYNC_FLUSH);
    72     env->ReleaseByteArrayElements(in, inStart, 0);
    73     env->ReleaseByteArrayElements(out, outStart, 0);
    74     if (code == Z_OK || code == Z_STREAM_END) {
    75         jlong result = ((inLength - stream->avail_in) << 16) + outLength - stream->avail_out;
    76         if (code == Z_STREAM_END) {
    77             result |= ((jlong)1) << 32;
    78         }
    79         return result;
    80     }
    81     return -1024 + code;
    82 }

    成功编译出DeflatingDecompressor.dll文件。

    然后在的j2se工程的DeflatingDecompressor.java中使用

    1 static {
    2     System.loadLibrary("libs/DeflatingDecompressor");
    3 }

    加载动态库,得到

    1 Exception in thread "main" java.lang.UnsatisfiedLinkError: D:WorksTextLayoutNewReaderSElibsDeflatingDecompressor.dll: Can't find dependent libraries
    2     at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    3     at java.lang.ClassLoader.loadLibrary0(Unknown Source)
    4     at java.lang.ClassLoader.loadLibrary(Unknown Source)
    5     at java.lang.Runtime.loadLibrary0(Unknown Source)
    6     at java.lang.System.loadLibrary(Unknown Source)
    7     at org.amse.ys.zip.DeflatingDecompressor.<clinit>(DeflatingDecompressor.java:7)

    使用 DependencyWalker 查看DeflatingDecompressor.dll的依赖关系,发现缺少zlib1.dll, 这时候我想起来下载的zlib发布中还有一个动态库,拷贝到System32文件夹下,再试,果然可以了。

    那么这时候为什么呢?经过资料查询才知道VS编译出来的lib文件有静态和动态lib的区别,简单的说:静态lib就是把所有的代码一股脑编译进lib文件中,在使用的时候配合头文件和lib文件就可以直接用了。而动态lib则是伴随着dll生成的,其中只包含了动态加载dll的代码,通过在程序中引用它,就可以省去了显式的调用dll的繁琐。

    如何判断一个lib是静态还是动态的呢?我没有找到好的办法,一般来说,静态lib的发布只有两个文件:一个头文件定义了lib中的开放接口,一个.lib文件则是实现的内容;而动态lib的文件发布包含一个头文件,一个dll文件,一个lib文件,往往还有一个def文件来列出dll中的接口。根据这个就可以判断了。

    好了,这就是调用没有成功的原因,我本来已经加载的lib是一个静态lib, 其实它是一个动态lib

  • 相关阅读:
    GC算法 垃圾收集器
    JVM内存结构
    java类的加载机制
    Spring Boot:Web 综合开发
    构建微服务:Spring boot 入门篇
    Spring Boot:Spring Boot 中 Redis 的使用
    Spring Boot:Thymeleaf 使用详解
    Android ActionBar完全解析,使用官方推荐的最佳导航栏(下)
    用ActionBar的ActionProvider的时候报错:cannot be cast to android.view.ActionProvider
    百度图片API
  • 原文地址:https://www.cnblogs.com/yueang/p/3156402.html
Copyright © 2020-2023  润新知