NDK how to get the dvm point? - java

now I have a question to use "JNI_GetCreatedJavaVMs".
but I couldn't use JNI_OnLoad method because my native code is not provid for java .
void *pHandle = dlopen("/system/lib/libart.so", RTLD_NOW | RTLD_GLOBAL);
JavaVM* m_pJvm = NULL;
void * pFunAddr =dlsym(pHandle, "JNI_GetCreatedJavaVMs");
LOGD("pJNI_GetCreatedJavaVMs = %08X", pFunAddr);
pJNIGetCreatedJavaVMs = (int)pFunAddr - 1;
LOGD("call !!!!!!!");
pJNIGetCreatedJavaVMs(&m_pJvm, 0, &vm_count);
LOGD("pJNIGetCreatedJavaVMs result is %d", result);
when I call the JNI_GetCreatedJavaVMs, process was crashed.
I didn't found what happend in IDA.
who can help me !!!!!!!!!!!!!! THX
ps:JNI_GetCreatedJavaVMs method is found in the android source code.
and another method is use runtime(libart.so) or gdvm(libdvm.so).

Some code from my native app, it is build in the AOSP source tree.
I am not sure if it could work in NDK
#include <jni.h>
#include <android_runtime/AndroidRuntime.h>
...
JNIEnv *env;
jint res;
JavaVM *jvm = AndroidRuntime::getJavaVM();
assert(jvm != NULL);
res = jvm->AttachCurrentThread(&env, NULL);
assert(res >= 0);

Related

While working with ffmpeg: Created function in C file and after compilation with NDK accessing from android activity, getting signal 11 error

After successfully fire command ndk-build I got .so file in my libs folder, then after some changes in gradle file I got native_libs.xml .idea/libraries folder.
Now I am accessing c function from my java code/ android activity. I am getting signal 11 error
My code is
C file
#include <jni.h>
#include <android/log.h>
#include <stdlib.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#define LOG_TAG "mylib"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
//JNIEXPORT jint JNICALL Java_com_xxx_xxx_activities_SplashActivity_logFileInfo(JNIEnv * env, jobject this, jstring filename);
jint Java_com_xxx_xxx_activities_TutorialsActivity_logFileInfo(JNIEnv * env, jobject this, jstring filename)
{
av_register_all();
AVFormatContext *pFormatCtx;
const jbyte *str;
str = (*env)->GetStringUTFChars(env, filename, NULL);
if(avformat_open_input(&pFormatCtx, str, NULL, NULL)!=0)
{
LOGE("Can't open file '%s'\n", str);
return 1;
}
else
{
LOGI("File was opened\n");
LOGI("File '%s', Codec %s",
pFormatCtx->filename,
pFormatCtx->iformat->name
);
}
return 0;
}
Loading and try to access method in java code is
private static native int logFileInfo(String filename);
static {
System.loadLibrary("framegrabber");
}
In OnCreate of activity
logFileInfo(file.getAbsolutePath());
Finally error at point logFileInfo(file.getAbsolutePath()); is
A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x106e in tid 8905 (Thread-20972)
Please replay if you have any solution, Thanking in advance.

How to use JNI to start JVM in builder C++ application

So i need to use jni to call java method.
i started with this code :
JNIEnv *env1;
JavaVM** jvm1;
JavaVMInitArgs vm_args1;
JavaVMOption options1[1];
options1[0].optionString = "-Djava.class.path=D:\\Java Src\\TestStruct"; //Path to the java source code
vm_args1.version = JNI_VERSION_1_6; //JDK version. This indicates version 1.6
vm_args1.nOptions = 1;
vm_args1.options = options1;
vm_args1.ignoreUnrecognized = 0;
int reAt = JNI_CreateJavaVM(jvm1, (void**)&env1, &vm_args1);
if(reAt < 0)
Label1->Caption = "failed";
else
Label1->Caption = "Success";
I convert jvm.lib to OMF lib for to use in my builder C++ Application :
COFF2OMF jvm.lib jvm2.lib
I added jvm2.lib to the library path to fixe link error about JNI_CreateJavaVM function.
Now my application compile without error.
But it crash when it call JNI_CreateJavaVM function.
I added the jvm.dll near my .exe
What is the pb in there steps??
How can fixe it?
Thx
The first argument to JNI_CreateJavaVM should be a valid pointer to JavaVM*:
JavaVM* jvm1;
int reAt = JNI_CreateJavaVM(&jvm1, ...);
In your example, jvm1 is uninitialized.
Consult the documentation for details.

JNI Call java method from c program

I need to call java method from c program. i have tried below code to call the java method through Java native interface but facing issues while compilation. i m new to C and have experience in java. so, i m not able to think myself what is happening while creating JVM.
Below is the code.
CTest.c
#include <stdio.h>
#include <jni.h>
JNIEnv* create_vm() {
JavaVM* jvm;
JNIEnv* env;
JavaVMInitArgs args;
JavaVMOption options[1];
args.version = JNI_VERSION_1_6;
args.nOptions = 1;
options[0].optionString = "-Djava.class.path=D:\\Ashish_Review\\JNI\\src";
args.options = options;
args.ignoreUnrecognized = JNI_FALSE;
JNI_CreateJavaVM(&jvm, (void **)&env, &args);
return env;
}
void invoke_class(JNIEnv* env) {
jclass helloWorldClass;
jmethodID mainMethod;
jobjectArray applicationArgs;
jstring applicationArg0;
helloWorldClass = (*env)->FindClass(env, "HelloWorld");
mainMethod = (*env)->GetStaticMethodID(env, helloWorldClass, "main", "([Ljava/lang/String;)V");
applicationArgs = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), NULL);
applicationArg0 = (*env)->NewStringUTF(env, "From-C-program");
(*env)->SetObjectArrayElement(env, applicationArgs, 0, applicationArg0);
(*env)->CallStaticVoidMethod(env, helloWorldClass, mainMethod, applicationArgs);
}
int main(int argc, char **argv) {
JNIEnv* env = create_vm();
invoke_class( env );
}
C:\Users\Desktop\tcc>tcc C:\TurboC++\Disk\TurboC3\BIN\CTest.c -I "C:\Program Files\Java\jdk1.6.0_16\include" -I "C:\Program Files\Java\jdk1.6.0_16\include\win32" -shared -o CTest.dll
tcc: undefined symbol '_JNI_CreateJavaVM#12'
please help me out.
The error message is about the linking stage, not compilation - you have included the header file, but to create the executable you have to specify the .a (library files) also.
You have to link with JVM's library (add some reference to libjvm.a to the tcc's command line).
If you don't have a precompiled jvm.lib file for TurboC++, there is another option - link with the jvm.dll file and export all the methods from JVM manually. This uses the LoadLibrary/GetProcAddress functions.
For a short sample (sorry, couldn't find the entire export source code), look at this:
/* load library */
HMODULE dll = LoadLibraryA("jvm.dll");
/* declare a function pointer and initialize it with the "pointer" to dll's code */
JNI_CreateJavaVM_func JNI_CreateJavaVM_ptr = GetProcAddress(dll, "JNI_CreateJavaVM");
Later use the JNI_CreateJavaVM_ptr instead of JNI_CreateJavaVM. Also you'll have to declare the JNI_CreateJavaVM_func type - you might just copy the signature from "jni.h"

JVM created via JNI in C doesn't work

I'm quite new to JNI and right now I'm using this simple C program to create a JVM and call the main() from my Java project:
#include <stdio.h>
#include <jni.h>
JNIEnv* create_vm() {
JavaVM* jvm;
JNIEnv* env;
JavaVMInitArgs args;
JavaVMOption options[1];
args.version = JNI_VERSION_1_6;
args.nOptions = 1;
options[0].optionString = "-Djava.class.path=CLASSPATH"; //This isn't the actual classhpath, but you get the idea
args.options = options;
args.ignoreUnrecognized = JNI_FALSE;
int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
if (ret<0){
printf("\nUnable to Launch JVM");
} else {
printf("\nJVM launched successfully");
}
return env;
}
void invoke_class(JNIEnv* env) {
jclass UncaughtExceptionClass;
jmethodID mainMethod;
jobjectArray applicationArgs;
jstring applicationArg0;
UncaughtExceptionClass = (*env)->FindClass(env, "exceptioncatcher/ExceptionCatcher");
mainMethod = (*env)->GetStaticMethodID(env, UncaughtExceptionClass, "main", "([Ljava/lang/String;)V");
applicationArgs = (*env)->NewObjectArray(env, 1, (*env)->FindClass(env, "java/lang/String"), NULL);
applicationArg0 = (*env)->NewStringUTF(env, "From C");
(*env)->SetObjectArrayElement(env, applicationArgs, 0, applicationArg0);
(*env)->CallStaticVoidMethod(env, UncaughtExceptionClass, mainMethod, applicationArgs);
}
int main(int argc, char **argv) {
JNIEnv* env = create_vm();
invoke_class( env );
}
This works well when running a HelloWorld type java code, but my code actually sets a Default Uncaught Exception Handler. This handler will send the info collected for each uncaught exception to a thread that will process them and send them by email.
Right now these are pretty much all the classes created and it, obviously, won't catch a lot of uncaught exceptions right now. But I use the main() to try it out:
public static void main(String[] args){
Thread.setDefaultUncaughtExceptionHandler(new DefaultExceptionHandler());
Integer i = null;
i++;
}
It works fine when I simply run it from netbeans, but the only thing that appears when using the C app is "JVM launched successfully".
Can anyone help on this one?
Managed to make it work in the end (never closed the question before), simply had to build the project and change the classpath to the .jar generated.

JNI UnsatisfiedLinkError on a native method

I'm running a basic Java wrapper for a C++ BSD socket client. I can compile the Java and generate a header file, but when I try to run it, it returns Exception in thread "main" java.lang.UnsatisfiedLinkError: JavaClient.socketComm()V
From what I've been able to find, it seems like this is indicative of a mismatch between method signatures, but I can't find anything wrong with mine.
Java Code
public class JavaClient
{
public native void socketComm();
public static void main(String[] args)
{
System.load("/home/cougar/workspace/ArbiterBSDSocketComms/JNIClient/JavaClient.so");
JavaClient client = new JavaClient();
client.socketComm();
System.out.println("Done");
}
}
C Implementation
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <cstdlib>
#include <stdio.h>
#include <jni.h>
#include "JavaClient.h"
#define MAXHOSTNAME 256
JNIEXPORT void JNICALL Java_JavaClient_socketComm
(JNIEnv *env, jobject obj) {
struct sockaddr_in remoteSocketInfo;
struct hostent *hPtr;
int socketHandle;
char *remoteHost="localhost";
int portNumber = 8080;
memset(&remoteSocketInfo, 0, sizeof(struct sockaddr_in)); //Clear structure memory
if ((hPtr = gethostbyname(remoteHost)) == NULL) //Get sysinfo
{
printf("System DNS resolution misconfigured.");
printf("Error number: ", ECONNREFUSED);
exit(EXIT_FAILURE);
}
if((socketHandle = socket(AF_INET, SOCK_STREAM, 0)) < 0) //Create socket
{
close(socketHandle);
exit(EXIT_FAILURE);
}
memcpy((char *)&remoteSocketInfo.sin_addr,
hPtr->h_addr, hPtr->h_length); //Load sys info into sock data structures
remoteSocketInfo.sin_family = AF_INET;
remoteSocketInfo.sin_port = htons((u_short)portNumber); //Set port number
if(connect(socketHandle, (struct sockaddr *)&remoteSocketInfo, sizeof(struct sockaddr_in)) < 0)
{
close(socketHandle);
exit(EXIT_FAILURE);
}
int rc=0;
char buf[512];
strcpy(buf, "Sup server");
send(socketHandle, buf, strlen(buf)+1, 0);
}
void main(){}
Header File
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class JavaClient */
#ifndef _Included_JavaClient
#define _Included_JavaClient
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: JavaClient
* Method: socketComm
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_JavaClient_socketComm
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
Excuse some of the bad formatting, I haven't used stackoverflow much and the code formatting is a bit sketchy.
These files all reside in /JNIClient.
I'm running Ubuntu 12.04 x64, and I have both 32- and 64-bit JDKs installed. I tried generating the .so with the 32-bit verison first, which would have been ideal, but I got an ELF mismatch, so I just went with the 64-bit so I wouldn't have to deal with that. (Any insight on that is welcome as well.)
My process is:
$>javac JavaClient.java
$>javah JavaClient
$>cc -m64 -g -I/usr/lib/jvm/java-6-openjdk-amd64/include -I/usr/lib/jvm/java-6-openjdk-amd64/include/linux -shared JavaClient.c -o JavaClient.so
$>java JavaClient
The full error message is
Exception in thread "main" java.lang.UnsatisfiedLinkError: JavaClient.socketComm()V
at JavaClient.socketComm(Native Method)
at JavaClient.main(JavaClient.java:9)
$>nm JavaClient.so returns:
cougar#Wanda:~/workspace/ArbiterBSDSocketComms/JNIClient$ nm JavaClient.so
0000000000200e50 a _DYNAMIC
0000000000200fe8 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
0000000000200e30 d __CTOR_END__
0000000000200e28 d __CTOR_LIST__
0000000000200e40 d __DTOR_END__
0000000000200e38 d __DTOR_LIST__
00000000000005e0 r __FRAME_END__
0000000000200e48 d __JCR_END__
0000000000200e48 d __JCR_LIST__
0000000000201010 A __bss_start
w __cxa_finalize##GLIBC_2.2.5
0000000000000540 t __do_global_ctors_aux
0000000000000490 t __do_global_dtors_aux
0000000000201008 d __dso_handle
w __gmon_start__
0000000000201010 A _edata
0000000000201020 A _end
0000000000000578 T _fini
0000000000000438 T _init
0000000000000470 t call_gmon_start
0000000000201010 b completed.6531
0000000000201018 b dtor_idx.6533
0000000000000510 t frame_dummy
Edit: I have a theory that the .so is being built improperly, as $>nm JavaClient.so doesn't show the method names in it. Any suggestions on what's wrong about that cc command?
Okay, SO: I kept at this because nothing seemed right. The method signatures were all matched, nothing should be wrong, eclipse file properties said it was editing the right file, etc etc. I finally catted the JavaClient.c, and it was blank. Apparently eclipse wasn't ACTUALLY editing the file it said it was. Fixed that up and now everything's fine.
I will give you a far better solution.
public void socketComm() throws IOException
{
Socket socket = new Socket("localhost", 8080);
try
{
socket.getOutputStream().write("Sup server\u0000".getBytes());
}
finally
{
socket.close(); // You forgot this
}
}
No JNI required at all. It also doesn't close an invalid handle if socket() returns < 0, unlike your code.
I kept at this because nothing seemed right. The method signatures were all matched, nothing should be wrong, eclipse file properties said it was editing the right file, etc etc. I finally catted the JavaClient.c, and it was blank. Apparently eclipse wasn't ACTUALLY editing the file it said it was. Fixed that up and now everything's fine.
Not sure why Eclipse claimed to be editing a blank file, I checked and rechecked and it wasn't referencing any links or anything, but if you're having the same problem as me check it out.

Categories

Resources