Java JNI LoadLibrary protected dll - java

I created JNI export dll with visual c++ with one simple function. it work correctly when i use it in my java code with LoadLibrary method.
but when i use Unikey Enveloper and protected this dll it not work in java and this error appear
Invalid access to memory location
when i test this protected dll with visual c++ console application it work correctly.
how can I use protected dll in java LoadLibrary Method?
Visual C++ Code:
extern "C" {
JNIEXPORT jint JNICALL Java_Bikaran_Start_JniTestFunction(JNIEnv *env, jclass c, jint a, jint b)
{
return a + b;
}
}
JAVA Code :
package Bikaran;
public class Start {
public static native int JniTestFunction(int s, int s1);
public static void main(String[] args) {
System.loadLibrary("...");
System.out.println(JniTestFunction(1,2));
}
}

Related

JNI and constructors

I have a compiled library that I need to use in a project. To keep it short, it's a library for interacting with a specific piece of hardware. What I have is .a and .dll library files, for linux and windows respectively, and a bunch of C++ .h headers with all the public functions and classes described there.
The problem is that the project needs to be in Java, so I need to write a JNI wrapper for this library, and honestly, I've never done that. But that's ok, I'm down to learn the thing.
I've read up a bunch of documentation online, and I figured out passing variables, creating java objects from native code, etc.
What I can't figure out, is how to work with native constructors using JNI? I have no idea what the source code of these constructors are, I only have the headers like this:
namespace RFDevice {
class RFDEVICE_API RFEthernetDetector
{
public:
//-----------------------------------------------------------------------------
// FUNCTION RFEthernetDetector::RFEthernetDetector
/// \brief Default constructor of RFEthernetDetector object.
///
/// \return void : N/A
//-----------------------------------------------------------------------------
RFEthernetDetector();
RFEthernetDetector(const WORD wCustomPortNumber);
So basically if I was to write my program in C++ (which I can't), I would do something like
RFEthernetDetector ethernetDetector = new RFEthernerDetector(somePort);
and then work with that object. But... How do I do this in Java using JNI?
I don't understand how am I supposed to create a native method for constructor, that would call the constructor from my .a library, and then have some way of working with that specific object? I know how to create java objects from native code - but the thing is I don't have any information about internal structure of the RFEthernetDetector class - only some of it's public fields and public methods.
And I can't seem to find the right articles on the net to help me out. How do I do that?
Update: A bit further clarification.
I create a .java wrapper class like this:
public class RFEthernetDetector
{
public RFEthernetDetector(int portNumber)
{
Init(portNumber);
}
public native void Init(int portNumber); // Void? Or what?
}
then I compile it with -h parameter to generate JNI .h file:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class RFEthernetDetector */
#ifndef _Included_RFEthernetDetector
#define _Included_RFEthernetDetector
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: RFEthernetDetector
* Method: Init
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_RFEthernetDetector_Init
(JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif
I then create an implementation that will call the functions from my .a library:
#include "RFEthernetDetector.h" // auto-generated JNI header
#include "RFEthernetDetector_native.h" // h file that comes with the library,
//contains definition of RFEthernetDetector class
/*
* Class: RFEthernetDetector
* Method: Init
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_RFEthernetDetector_Init(JNIEnv *env, jobject thisObj, jint value)
{
RFEthernetDetector *rfeDetector = new RFEthernetDetector(value); // constructor from the library
// now how do I access this new object from Java?
// if I need to later call rfDetector->doSomething() on that exact class instance?
}
You would need to build a RFEthernetDetector Java class that, through a pointer, owns a RFEthernetDetector on the C++ side. This is no fun, but inter-language glue never is.
// In this design, the C++ object needs to be explicitly destroyed by calling
// close() on the Java side.
// I think that Eclipse, at least, is configured by default to complain
// if an AutoCloseable is never close()d.
public class RFEthernetDetector implements AutoCloseable {
private final long cxxThis; // using the "store pointers as longs" convention
private boolean closed = false;
public RFEthernetDetector(int port) {
cxxThis = cxxConstruct(port);
};
#Override
public void close() {
if(!closed) {
cxxDestroy(cxxThis);
closed = true;
}
}
private static native long cxxConstruct(int port);
private static native void cxxDestroy(long cxxThis);
// Works fine as a safety net, I suppose...
#Override
#Deprecated
protected void finalize() {
close();
}
}
And on the C++ side:
#include "RFEthernetDetector.h"
JNIEXPORT jlong JNICALL Java_RFEthernetDetector_cxxConstruct(JNIEnv *, jclass, jint port) {
return reinterpret_cast<jlong>(new RFEthernetDetector(port));
}
JNIEXPORT void JNICALL Java_RFEthernetDetector_cxxDestroy(JNIEnv *, jclass, jlong thiz) {
delete reinterpret_cast<RFEthernetDetector*>(thiz);
// calling other methods is similar:
// pass the cxxThis to C++, cast it, and do something through it
}
If all that reinterpret_casting makes you feel uncomfortable, you could choose to instead keep a map around:
#include <map>
std::map<jlong, RFEthernetDetector> references;
JNIEXPORT jlong JNICALL Java_RFEthernetDetector_cxxConstruct(JNIEnv *, jclass, jint port) {
jlong next = 0;
auto it = references.begin();
for(; it != references.end() && it->first == next; it++) next++;
references.emplace_hint(it, next, port);
return next;
}
JNIEXPORT void JNICALL Java_RFEthernetDetector_cxxDestroy(JNIEnv *, jclass, jlong thiz) {
references.erase(thiz);
}
You'll need to build the native class in Java, then run the javah program which will build the stubs that Java expects. You'll then need to map the java stubs to the C++ code to compile and distribute that binding library along with your java program.
https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
So, what I ended up doing for now is basically storing the address in my .java class as "long" variable, and then have Init() method return the address of C++ instance as jlong.
Then, when I need to call something on that instance of a class - I pass the address as an additional argument and do the transformation in the C code like this (tested on test class / custom .so):
//constructor wrapper
JNIEXPORT jlong JNICALL Java_Test_Greetings(JNIEnv *env, jobject thisObj, jint value)
{
Greetings *greetings = new Greetings(value);
return (jlong)greetings;
}
JNIEXPORT void JNICALL Java_Test_HelloWorld(JNIEnv *env, jobject thisObj, jlong reference)
{
Greetings *greetings;
greetings = (Greetings*)reference;
greetings->helloValue();
}
I have no idea if that's the correct way to do it, but it works... would appreciate if someone tells me how wrong I am.

Adding native hooks dynamically

Is there some way to add native hooks dynamically using JNI? What I mean by that is, I would like to override some methods in a class (or in a new class) so that the override calls my native code, without writing any Java code for that.
If you are referring to native methods, maybe registering might be the answer for you.
For example, here, I am registering native method
JNIEXPORT jint JNICALL addOne(JNIEnv *env, jclass obj, jint a) {
return a + 1;
}
...
...
static JNINativeMethod methods[] = {
{"addOne", "(I)I", (void *)&addOne}
};
...
...
(*env)->RegisterNatives(env, cls_Main,
methods, sizeof(methods)/sizeof(methods[0]));
that will be assigned to class
public class Main {
public static native int addOne(int a);
...
...
}
Full sample: https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo052

How to connect mysql from a file written in C which contains native methods of java?

I need some way to connect MySQL with C which have Java JNI methods in it.
I made a Java file which calls a native method written in C which needs to be connected to MySQL database.
C File
#include <stdio.h>
#include <mysql/mysql.h>
#include "MyClass.h"
JNIEXPORT jstring JNICALL Java_pkg_MyClass_display(JNIEnv *env, jobject obj){
return (*env)->NewStringUTF(env,mysql_get_client_info());
}
Java File
public class MyClass {
public native String display();
public static String Disp(){
MyClass ob = new MyClass();
String str = ob.display();
return str;
}
static {
System.load("Desktop/libdemo.so");
}
public static void main(String []args){
System.out.println(Disp());
}
}
After creating shared object library (.so), an error occurs:
undefined reference to : mysql_get_client_info()
Please suggest some way to rectify this problem.

How can I send multiple strings from android Java to JNI?

I am trying to follow this
I have declared the JNI function as
JNIEXPORT void JNICALL Java_com_mypackage_myapp_MyJavaClass_Fun(JNIEnv* env, jobject object, jobjectArray stringArray)
And the corresponding Java function in MyJavaClass is declared as:
public native void Fun(String[] strArray);
But its not working for me as I keep getting run time error:
No implementation found for void com.mypackage.myapp.MyJavaClass.Fun(java.lang.String[])
I have also tried declaring Fun as
public native void Fun(List<String> strArray);
And
public native void Fun(ArrayList<String> strArray);
but these also result in same run time error

Android NDK calling native method with different namespace

i'm new from JNI programming
Can i call a native method like from a different JNI namespace definition?
For example:
package com.example.hellojni;
public class HelloJni extends Activity
{
public native int MyMethod();
public native int OtherMethod(); // this works have the namespace package=jniexport interface
static {System.loadLibrary("hello-jni");}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
int b = OtherMethod(); //works
int a = MyMethod(); //ERROR java.lang.reflect.InvocationTargetException
}
}
================File.c================
JNIEXPORT int JNICALL Java_Cardioline_HelloJni_MyMethod(JNIEnv *env, jobject thisObj)
{
return 1;
}
JNIEXPORT int JNICALL Java_com_example_hellojni_HelloJni_OtherMethod(JNIEnv *env, jobject thisObj)
{
return 2;
}
No, the JNI method name is predetermined by javah. Try starting here:
http://blog.edwards-research.com/2012/04/tutorial-android-jni/
javah will provide you with the header and you must copy the method declarations into your .c file.
If you have a JNI method in another class that you want to call, call the other class in java. Basically change this:
int a = MyMethod();
to this:
int a = new CardioLine.HelloJni().MyMethod();
Typically, I have a one-to-one mapping of Java files to .c/.cpp files. That's probably what you want too (for Java classes with native methods).
As #JonnyBoy explained in his answer, the name of a JNI native function is tightly coupled with the full name of the Java class that uses this function as a native method. The full name of HelloJni class in com.example.hellojni package is com.example.hellojni.HelloJni, thus it looks for native functions which names start with Java_com_example_hellojni_HelloJni_.
Luckily, there is no requirement in Android for all your classes to be under the app package. For example, your app that is registered as com.example.hellojni is free to include and use a package CardioLine and class CardioLine.HelloJni.
The directory structure for a simple Android project will include a tree like this:
src
com
example
hellojni
HelloJni.java
CardioLine
HelloJni.java
On the other hand, if you include JNI_OnLoad() function in your native library, and use RegisterNatives(), your Java class can have native methods regardless of their exported names.

Categories

Resources