在加载库Cryptopp上获得“Java结果:-1073741571”

时间:2014-09-06 19:06:17

标签: java java-native-interface native-code crypto++

我正在尝试将自定义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

1 个答案:

答案 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);
        }
    }
}

在您的情况下,它可能是Base64EncoderBase64Decoder

请记住,所有Crypto ++类对象都是线程安全的,这意味着它们无法访问全局或共享数据。但是当多个线程(错误)使用同一个对象时,它们并不安全。


我为JNI问题咨询的书是The Java Native Interface: Programmer's Guide and Specification


最后,抱歉&#34;回答&#34;。它不是一个真正的答案。相反,它是一个不适合评论块的大评论。