java espresso 自行车_回應albert_espresso: 由C呼叫java中的物件

--------------- 前言 -------------------------------------------------------------

基本上,從 C程式透過JNI而呼叫Java 物件之函數,其情境有三:

1) 獨立的C程式呼叫Java 函數

---- 這範例如下述michtw之回應

2) Java 線程進入Native C函數,再回頭呼叫Java 函數

3) Java 線程進入Native C函數,誕生子線程,由子線程呼叫Java 函數

---- 這範例請看下述由高老師寫的範例。

------------------------------------------------------------------------------------------

1. albert_espresso的原來問題:

小弟目前必須使用JNI的invocation API去cearteVM再找到特定的object並呼叫其方法, 呼叫物件方法如果由java call C的時候是很容易實作的因為與JVM的通道是由java打開 , 但是如果今天倒過來要由C呼叫java中的物件(與JVM的通道是由C打開)這樣的話就不是很清楚該怎麼做 , 因為C的部分是在linux下執行所以有想過應該是要create一個thread讓他可以使用invocation API指回JVM 再去找java物件 , 因為小弟我不熟linux的東西 , 不曉得各位是否可以推薦相關的網站或是資料可以給小弟參考 , 或是知道這種issue應該要由怎樣的方向下手會比較好 , 請給小弟一些建議

2. michtw回應的範例:

#include

#include

#include

JNIEnv* create_vm(JavaVM ** jvm)

{

JNIEnv *env;

JavaVMInitArgs vm_args;

JavaVMOption options[2];

options[0].optionString = "-Djava.compiler=NONE";

options[1].optionString = "-Djava.class.path=."; /* user classes */

vm_args.version = JNI_VERSION_1_4; //JDK version.

vm_args.options = options;

vm_args.nOptions = 2;

vm_args.ignoreUnrecognized = 0;

int ret = JNI_CreateJavaVM(jvm, &env, &vm_args);

if(ret < 0)

printf("\nUnable to Launch JVM %d\n",ret);

return env;

}

int main(int argc, char* argv[])

{

JNIEnv *env;

JavaVM * jvm;

env = create_vm(&jvm);

if (env == NULL)

return 1;

jclass clsH =NULL;

jmethodID midMain = NULL;

jmethodID midCalling = NULL;

clsH = env->FindClass("Hello");

if (clsH != NULL)

{

midMain       = env->GetStaticMethodID(clsH, "main", "([Ljava/lang/String;)V");

midCalling    = env->GetStaticMethodID(clsH,"TestCallMethod","(Ljava/lang/String;)V");

}

else

{

printf("\nUnable to find the requested class\n");

}

/************************************************************************/

/* Now we will call the functions using the their method IDs            */

/************************************************************************/

if(midMain != NULL)

env->CallStaticVoidMethod(clsH, midMain, NULL); //Calling the main method.

if (midCalling!=NULL)

{

jstring StringArg = env->NewStringUTF("\nTestCall:Called from the C Program\n");

//Calling another static method and passing string type parameter

env->CallStaticVoidMethod(clsH,midCalling,StringArg);

}

//Release resources.

int n = jvm->DestroyJavaVM();

return 0;

}

3. albert_espresso的再度說明問題:

你所提出的解答是屬於C要呼叫一般的java的做法 , 在android平台上不太一樣 , 在android上可以直接經由JNI_OnLoad(JavaVM *vm,void *reserved)直接取得指向android dalvik vm的ponter , 但現在我的問題是卡在 , 我將該pointer存在一個static global JavaVM* , 讓其他的thread可以使用 , 在一般的C呼叫java可行但是在android卻不行 , 找過很多相關的資料也都是相同的做法當然都不是android平台就是 , 換句話說android平台在invocation API這部分似乎和一般的JNI寫法應該有不同的地方 , 畢竟android的VM是自家做的跟一般的java VM有不同 , 不曉得有沒有人知道這個問題怎解 , 或是大家有不同的想法可以提出來討論一下

4. 高煥堂撰寫的範例:

// JTX05.java

package com.misoo.thread;

import java.lang.ref.WeakReference;

import com.misoo.pk01.ac01;

import android.os.Handler;

import android.os.Message;

import android.os.Process;

public class JTX05 {

private long refer;

private static Handler h;

private static int count;

static {

System.loadLibrary("JTX05_jni");

}

public JTX05(){

Init(new WeakReference(this));

count = 0;

h = new Handler(){

public void handleMessage(Message msg) {

count++;

if(count == 1) {

ac01.ref.setTitle("env: " + String.valueOf(msg.arg1));

}

else if(count == 2)

ac01.tv.setText("env: " + String.valueOf(msg.arg1));

}

};

}

public long calculate(){

execute(this);

//this.ssetTitle(ss);

//ac01.ref.setTitle("ss: " + ss);

return 0;

}

@SuppressWarnings("unused")

private static void callback(int a, int b){

Message m = h.obtainMessage(1, a, 3, null);

h.sendMessage(m);

}

private native void Init(Object weak_this);

private native String execute(Object oSync);

//private native String execute(int x);

}

/*  com_misoo_thread_JTX05.h    */

/* DO NOT EDIT THIS FILE - it is machine generated */

#include

/* Header for class com_misoo_thread_JTX05 */

#ifndef _Included_com_misoo_thread_JTX05

#define _Included_com_misoo_thread_JTX05

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class:     com_misoo_thread_JTX05

* Method:    nativeSetup

* Signature: (Ljava/lang/Object;)V

*/

JNIEXPORT void JNICALL Java_com_misoo_thread_JTX05_Init

(JNIEnv *, jobject, jobject);

/*

* Class:     com_misoo_thread_JTX05

* Method:    execute

* Signature: (J)J

*/

JNIEXPORT jstring JNICALL Java_com_misoo_thread_JTX05_execute

(JNIEnv *, jobject, jobject);

#ifdef __cplusplus

}

#endif

#endif

/*  com_misoo_thread_JTX05.cpp    */

#include "com_misoo_thread_JTX05.h"

#include

#include

#include

#include "android_runtime/AndroidRuntime.h"

using namespace android;

JavaVM *gJavaVM;

jmethodID   mid;

jclass      mClass;     // Reference to JTX05 class

jobject     mObject;    // Weak ref to JTX05 Java object to call on

char sTid[20];

unsigned int e1;

int x;

int sum;

pthread_t thread;

void* trRun( void* );

typedef multimap *> MapOfObjects;

//--------------------------------------------------------------

void Thread_sleep(int t)

{

timespec ts;

ts.tv_sec = t;

ts.tv_nsec = 0;

nanosleep(&ts, NULL);

return;

}

JNIEXPORT void JNICALL

Java_com_misoo_thread_JTX05_Init(JNIEnv *env, jobject thiz, jobject weak_this)

{

jclass clazz = env->GetObjectClass(thiz);

mClass = (jclass)env->NewGlobalRef(clazz);

mObject  = env->NewGlobalRef(weak_this);

mid = env->GetStaticMethodID(mClass, "callback","(II)V");

return;

}

JNIEXPORT jstring JNICALL

Java_com_misoo_thread_JTX05_execute(JNIEnv *env, jobject thiz, jobject syncObj){

//-----------------------------------------------------------

env->CallStaticVoidMethod(mClass, mid, 111, 0);

//-----------------------------------------------------------

int rr = pthread_create( &thread, NULL, trRun, NULL);

//-----------------------------------------------------------

long pid = getpid();

sprintf(sTid, "%lu", pid);

jstring ret = env->NewStringUTF(sTid);

return ret;

}

//--------------------------------------------------------------------

static const char *classPathName = "com/misoo/thread/JTX05";

static JNINativeMethod methods[] = {

{"init",       "(Ljava/lang/Object;)V",

(void *)Java_com_misoo_thread_JTX05_Init},

{"execute",    "(Ljava/lang/Object;)Ljava/lang/String;",

(void *)Java_com_misoo_thread_JTX05_execute}

};

/*

* Register several native methods for one class.

*/

static int registerNativeMethods(JNIEnv* env, const char* className,

JNINativeMethod* gMethods, int numMethods)

{

jclass clazz;

clazz = env->FindClass(className);

if (clazz == NULL) {

LOGE("Native registration unable to find class '%s'", className);

return JNI_FALSE;

}

if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {

LOGE("RegisterNatives failed for '%s'", className);

return JNI_FALSE;

}

return JNI_TRUE;

}

static int registerNatives(JNIEnv* env)

{

if (!registerNativeMethods(env, classPathName,

methods, sizeof(methods) / sizeof(methods[0]))) {

return JNI_FALSE;

}

return JNI_TRUE;

}

// ----------------------------------------------------------------------------

jint JNI_OnLoad(JavaVM* vm, void* reserved)

{

JNIEnv *env;

gJavaVM = vm;

int result;

LOGI("JNI_OnLoad called");

if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {

LOGE("Failed to get the environment using GetEnv()");

return -1;

}

if (registerNatives(env) != JNI_TRUE) {

LOGE("ERROR: registerNatives failed");

goto bail;

}

result = JNI_VERSION_1_4;

bail:

return result;

}

//--------------------------------------------------------------------------------

void* trRun( void* )

{

int status;

JNIEnv *env;

bool isAttached = false;

Thread_sleep(1);

status = gJavaVM->GetEnv((void **) &env, JNI_VERSION_1_4);

if(status < 0) {

LOGE("callback_handler: failed to get JNI environment, "

"assuming native thread");

status = gJavaVM->AttachCurrentThread(&env, NULL);

if(status < 0) {

LOGE("callback_handler: failed to attach "

"current thread");

return NULL;

}

isAttached = true;

}

//-----------------------------------------------------------

env->CallStaticVoidMethod(mClass, mid, 222, 0);

//-----------------------------------------------------------

if(isAttached)

gJavaVM->DetachCurrentThread();

return NULL;

}

~~ END ~~

(misoo)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值