我正在尝试将自定义c ++ dll (使用jni)加载到java,但我有一个问题:我的dll使用cryptopp库,当java尝试加载取决于(包括cryptopp),应用程序退出并显示以下消息:
Java结果: -1073741571
那是什么,我可以在不删除cryptopp的情况下解决这个问题吗?
更新
如果我评论文件zCypto.h和zCypro.cpp,并删除了cryptopp库的所有用法,它的工作没有任何错误,如果加载cryptopp就会抛出错误。 Java代码:
public static void main(String[] args){
System.loadLibrary("cryptopp");
System.loadLibrary("ZCPP_Code64");
}
CPP Source(我在Visual Studio 2012中创建dll):
#include "zCrypto.h"
JNIEXPORT void JNICALL Java_ru_zontwelg_Loader_loadCache
(JNIEnv *env, jobject jobj)
{
std::fstream stream;
stream.open("C:\\testing_capturing\\enc.zwac", ios_base::binary | ios_base::in);
// Other decode & read stuff here ...
stream.close();
}
部首:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class ru_zontwelg_Loader */
#ifndef _Included_ru_zontwelg_Loader
#define _Included_ru_zontwelg_Loader
extern "C" {
/*
* Class: ru_zontwelg_Loader
* Method: loadCache
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_ru_zontwelg_Loader_loadCache
(JNIEnv *, jobject);
}
#endif
zCrypto.h:
#ifndef ZontWelg_zCrypto
#define ZontWelg_zCrypto
#include <dll.h>
#include <cstdio>
#include <Windows.h>
#include <iostream>
#include "cryptlib.h"
using CryptoPP::Exception;
#include "hex.h"
using CryptoPP::HexEncoder;
using CryptoPP::HexDecoder;
#include "base64.h"
using CryptoPP::Base64Encoder;
using CryptoPP::Base64Decoder;
#include "filters.h"
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::StreamTransformationFilter;
#include "sha.h"
#include "rsa.h"
#include "hex.h"
#include "osrng.h"
#include "secblock.h"
#include "modes.h"
#include "aes.h"
using CryptoPP::AES;
//#include "ccm.h"
using CryptoPP::CBC_Mode;
#pragma comment(lib, "cryptlib.lib")
//#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "cryptopp.lib")
using namespace std;
class zCrypto {
public:
static string base64(string in);
static string from_base64(string in);
static string decrypt(const std::string& str_in);
};
#endif
答案 0 :(得分:1)
这对我来说很奇怪,但我不是任何一个JNI专家:
public static void main(String[] args){
System.loadLibrary("cryptopp");
System.loadLibrary("ZCPP_Code64");
}
我希望看到类似的东西(来自我的一个Crypto ++ / Android / JNI项目):
public class PRNG {
static {
System.loadLibrary("stlport_shared");
System.loadLibrary("cryptopp");
System.loadLibrary("prng");
}
private static native int CryptoPP_Reseed(byte[] bytes);
private static native int CryptoPP_GetBytes(byte[] bytes);
private static Object lock = new Object();
// Returns the number of bytes consumed.
public static int Reseed(byte[] seed) {
synchronized (lock) {
return CryptoPP_Reseed(seed);
}
}
// Returns the number of bytes generated.
public static int GetBytes(byte[] bytes) {
synchronized (lock) {
return CryptoPP_GetBytes(bytes);
}
}
}
不要担心stlport_shared
,因为它是Android的东西。
这看起来很奇怪:
#pragma comment(lib, "cryptlib.lib")
//#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "cryptopp.lib")
因为您正在调用System.loadLibrary("cryptopp")
,这意味着您正在使用Crypto ++ DLL。这也意味着不需要这样做:#pragma comment(lib, "cryptlib.lib")
。选择静态链接或动态链接,但不能同时选择两者。
如果您(1)构建了ZCPP_Code64
DLL,并且(2)静态链接到Crypto ++,那么这可能是最简单的。然后你的静态加载器看起来像:
static {
System.loadLibrary("ZCPP_Code64");
}
如果你选择了针对Crypto ++的静态链接,那么你可能需要重建静态库。这是因为您将以此配置结束:
Your DLL -> dynamic linking against the C Runtime
Crypto++ LIB -> static linking against the C Runtime
这将导致一堆重复的符号(C运行时符号)。你想要的是:
Your DLL -> dynamic linking against the C Runtime
Crypto++ LIB -> dynamic linking against the C Runtime
要修复它,请打开Cryptlib项目,并将Runtime链接对象从静态更改为动态。请参阅&#34;静态与动态链接&#34;在Compiling and Integrating Crypto++ into the Microsoft Visual C++ Environment。
这对我来说没问题:
JNIEXPORT void JNICALL Java_ru_zontwelg_Loader_loadCache
(JNIEnv *env, jobject jobj)
{
...
}
我不确定...哪些本地库需要位于Windows上。为此,请查看Java JNI and dependent libraries on Windows。
如果多个线程访问相同的底层Crypto ++对象,您还必须执行锁定。就我而言,底层对象是AutoSeededRandomPool
:
public class PRNG {
...
// Returns the number of bytes consumed.
public static int Reseed(byte[] seed) {
synchronized (lock) {
return CryptoPP_Reseed(seed);
}
}
// Returns the number of bytes generated.
public static int GetBytes(byte[] bytes) {
synchronized (lock) {
return CryptoPP_GetBytes(bytes);
}
}
}
在您的情况下,它可能是Base64Encoder
或Base64Decoder
。
请记住,所有Crypto ++类对象都是线程安全的,这意味着它们无法访问全局或共享数据。但是当多个线程(错误)使用同一个对象时,它们并不安全。
我为JNI问题咨询的书是The Java Native Interface: Programmer's Guide and Specification。
最后,抱歉&#34;回答&#34;。它不是一个真正的答案。相反,它是一个不适合评论块的大评论。