1

I'm trying to load custom c++ dll (using jni) to java, but i have a problem: my dll using cryptopp library, and when java tries to load depending (including cryptopp), the application quits with the message:

Java Result: -1073741571

What is that, can i fix this without removing cryptopp?


Update:

If i commented files zCypto.h and zCypro.cpp, and deleted all usage of cryptopp library, it works without any errors, error has thrown if i load cryptopp. Java code:

public static void main(String[] args){
    System.loadLibrary("cryptopp");
    System.loadLibrary("ZCPP_Code64");
}

CPP Source (I make dll in Visual Studio 2012):

#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();
}

Header:

/* 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
Draiget
  • 113
  • 11
  • It's hard to tell what you're doing wrong, without seeing your code. Can you try making the smallest possible program that exhibits this problem, and pasting it in here? – Dawood ibn Kareem Sep 06 '14 at 19:11
  • Possible duplicate of [Eclipse: Java was started but returned exit code -1073741571](http://stackoverflow.com/questions/14022257/eclipse-java-was-started-but-returned-exit-code-1073741571). This can be tricky to search for because Google interprets the minus sign to mean "remove 1073741571 from results". Try this search: [Java "-1073741571"](https://www.google.com/#q=Java+Result%3A+%22-1073741571%22). – jww Sep 06 '14 at 19:23
  • @Draiget - We need more details. Is this an Android/Ecplise project? Is this a Windows project (possibly from the potential duplicate). How much memory does the VM have? Did you use `javah` to generate the C/C++ headers from your Java class files? Are you calling into your DLL exclusively? Or are you calling the Crypto++ DLL on occasion? – jww Sep 06 '14 at 19:32
  • @jww - I try to search error without "-", but could not find anything that referred to my problem. This is Java Application project in NetBeans (writed under Windows), and dll is c++ dynamic library (written in Visual Studio 2012). For generate headers i use `javah` – Draiget Sep 07 '14 at 06:42

1 Answers1

1

This looks odd to me, but I'm not a JNI expert by any stretch:

public static void main(String[] args){
    System.loadLibrary("cryptopp");
    System.loadLibrary("ZCPP_Code64");
}

I would expect to see something like (from one of my Crypto++/Android/JNI projects):

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

Don't worry about the stlport_shared because its an Android thing.


This also looks odd:

#pragma comment(lib, "cryptlib.lib")
//#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "cryptopp.lib")

Because you are calling System.loadLibrary("cryptopp"), that means you are using the Crypto++ DLL. It also means this is not needed: #pragma comment(lib, "cryptlib.lib"). Pick static linking or dynamic linking, but not both.

It would probably be easiest if you (1) built your ZCPP_Code64 DLL, and (2) statically linked to Crypto++. Then your static loader would look like:

    static {
        System.loadLibrary("ZCPP_Code64");
    }

If you choose static linking against Crypto++, then you will probably have to rebuild the static lib. That's because you'll end up in this configuration:

Your DLL -> dynamic linking against the C Runtime
Crypto++ LIB -> static linking against the C Runtime

That will cause a bunch of duplicate symbols (C Runtime symbols). What you want is:

Your DLL -> dynamic linking against the C Runtime
Crypto++ LIB -> dynamic linking against the C Runtime

To fix it, you open the Cryptlib project, and change the Runtime linking object from static to dynamic. See "Static Versus Dynamic Linking" at Compiling and Integrating Crypto++ into the Microsoft Visual C++ Environment.


This looks OK to me:

JNIEXPORT void JNICALL Java_ru_zontwelg_Loader_loadCache 
(JNIEnv *env, jobject jobj)
{
    ...
}

What I am not sure about... where native libraries need to be located on Windows. For that, take a look at Java JNI and dependent libraries on Windows.


You are also going to have to perform locking if multiple threads access the same underlying Crypto++ object. In my case, the underlying object was an 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);
        }
    }
}

In you case, it might be a Base64Encoder or Base64Decoder.

Remember, all Crypto++ class objects are thread safe meaning they don't access global or shared data. But they are not safe when multiple threads (mis)use the same object.


The book I consult for JNI issues is The Java Native Interface: Programmer's Guide and Specification.


Finally, sorry about the "answer". Its not really an answer. Rather, its a large comment that would not fit in a comment block.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • Thanks for detailed post, but i getting error (`Java Result: -1073741571`) when java loading compiled 64x crypto++ `System.load("\\cryptopp.dll");` or `System.loadLibrary("cryptopp");` – Draiget Sep 07 '14 at 08:40
  • @Draiget - Have you taken a look at [Java JNI and dependent libraries on Windows](http://stackoverflow.com/questions/12566732/java-jni-and-dependent-libraries-on-windows)? – jww Sep 07 '14 at 08:49
  • This should work: `System.load("\\cryptopp.dll")`. Are all components for the same platform? I.e., is Java 64-bit, is your DLL 64-bit, and is Crypto++ 64-bit? – jww Sep 07 '14 at 09:01
  • I copied crypto++ in windows directory, I also look depending libraries in **Dependency Walker** and he using only `KERNEL32.dll` and `ADVAPI32.dll`. Yes, all libraries are 64-bit including JDK. – Draiget Sep 07 '14 at 09:06