简体   繁体   中英

How to call unmanaged function which throws java.io.Exception in shared library from dotnet core

I have internal library that communicates with a special hardware. It is designed to call from java environment and uses JNI to export/extern functions. I am able call this kind of functions but an exception(java.io.Exception) thrown one of these functions and it is not catchable from dotnet core.

Created samples for describing the situation.

Hello.java

import java.io.IOException;
public class Hello {
    static {
        System.loadLibrary("native");
    }
    private native void test1();
    private native void test2() throws IOException;
}

Hello.h ( generated by javac -h. Hello.java )

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

#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Hello
 * Method:    test1
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Hello_test1
  (JNIEnv *, jobject);

/*
 * Class:     Hello
 * Method:    test2
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Hello_test2
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Hello.cpp ( implementation sample )

#include <jni.h>
#include "iostream"

#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Hello
 * Method:    test1
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Hello_test1
  (JNIEnv *, jobject) 
{
  std::cout << "Hello from C++ !!" << std::endl;
}

/*
 * Class:     Hello
 * Method:    test2
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Hello_test2
  (JNIEnv* env, jobject) {
  jclass Exception = env->FindClass("java/lang/Exception");
  env->ThrowNew(Exception, "something went wrong"); // Error Message  
}

#ifdef __cplusplus
}
#endif
#endif

Craeted a new library called native (like libnative.so) using this samples. test1 function is working properly but test2 is not. Here is my pure native invocation.

using System.Runtime.InteropServices;

namespace sample
{
    class MainClass
    {
        [DllImport("libnative.dylib")]
        public static extern void Java_Hello_test1();

        [DllImport("libnative.dylib", SetLastError = true)]
        public static extern void Java_Hello_test2();

        public static void Main(string[] args)
        {
            Java_Hello_test1();

            // crash with code 139 (segmentation fault)
            Java_Hello_test2();
        }
    }
}

I am using dotnet core 5.0 on linux and I wonder what is a proper solution.

You want JVM features to work within .NET? That's simply not possible.

If you are looking for a proper solution, it would be one of:

  • Port the Java application to .NET (or the other way around) to make sure there's only one VM running your code

  • Use an implementation of .NET on top of Java so JNI will still work and the implementation will take care of translating the exceptions. Maybe IKVM.NET?

  • Run the Java program and the .NET program as separate processes and use IPC to communicate between them.

JNIEnv* object is C programming interface for the whole Java runtime. It contains methods to load classes, call methods of objects, and so on, here's some documentation .

Realistically, you can't implement that interface yourself, way too much work. It would mean implementing major parts of JRE.

A proper solution is integrating JVM. See that library http://jni4net.com/ I don't have any experience, but at the first sight it's good enough and might do what you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM