【问题标题】:C attach to existing jvmC附加到现有的jvm
【发布时间】:2014-08-07 18:25:30
【问题描述】:

我需要从 C 代码中调用一些 Java 函数。我找到了一些关于如何从 C 创建新 jvm 的教程,但我需要一个现有的 jvm(我知道她的 PID)。此外,在我的例子中,Java 使用 JNI 调用了 C dll,我需要从 C 回调该 JVM。

这是我的代码的一部分:

JAVA:

public class HelloJNI {

    static {
        // hello.dll on Windows or libhello.so on Linux
        System.loadLibrary("hello");
    }

    // native method for call C dll
    private native String getHello(int jvmProcessId);

    public String doHello(){
        return getHello(myProcessId);
    }
}

C:

#include "hellojni_actions_HelloJNI.h"

void invoke_class(JNIEnv* env) {
    // HERE I NEED TO CALL A METHOD OF JAVA CLASS WHICH LOADED ME (HelloJNI.java) IN THE SAME JVM
}

JNIEXPORT jstring JNICALL Java_hellojni_actions_HelloJNI_getHello
  (JNIEnv *env, jobject thisObj, jint jvmProcessId){
    invoke_class(env);
    return (*env)->NewStringUTF(env, "Testing...");

}

【问题讨论】:

  • 不清楚您在问什么,因为您显示的代码似乎暗示 C DLL 已加载到 JVM 进程中。无论如何,你可以阅读stackoverflow.com/questions/22441878/…
  • 我同意,重读后请说明您的本机代码是否已加载到 JVM 中,或者您是否尝试将本机代码“注入”到已运行的 VM 中。

标签: java c eclipse jvm java-native-interface


【解决方案1】:

我前段时间做过类似的事情,可以粘贴一些代码片段(要进行错误检查):

请注意,调用的方法是obj的对象方法

void callJavaMethod( JNIEnv *env, jobject obj )
{
     jclass    cl;
     jmethodID id;
     jstring   js1;
     jstring   js2;
     jobject   byteArray;

     /* Im looking for byte[] javaMethod( String s1, String s2 ) */
     cl = (*env)->GetObjectClass( env, obj );
     id = (*env)->GetMethodID( env, cl, "javaMethod", "(Ljava/lang/String;Ljava/lang/String;)[B" );

     /* and now it's called */
     js1 = (*env)->NewStringUTF(env, "Hello");
     js2 = (*env)->NewStringUTF(env, "Java");

     byteArray = (*env)->CallObjectMethod( env, obj, js1, js2 );
     /* for other return types there are other CallxxxMethod() functions */

     ...
}

Java 7 的 JNI API 文档可以在 here 找到(Java 6 应该完全一样)

【讨论】:

  • 这就是我所做的。但是 JNIEnv 是您从调用 Java 类中收到的吗?如果我尝试在其中搜索某些类,我将收到 ClassDefNotFoundException。
  • 是的,JNIEnv 是调用 C 代码的 JVM 环境。您应该可以通过调用(*env)->FindClass( env, name ) 找到课程。请注意,name 必须是完全合格的,例如"java/lang/String",不仅仅是"String"
  • 与其在 C 中查找类,然后调用适当的构造函数等,不如在 Java 中创建一个对象并将其作为 jobject 参数传递给 jni 函数可能更容易
  • 好的,刚刚完成,它可以工作了。但是当我尝试在 c++ 中做同样的事情时(更改 FindClass 的签名,FindMethod... for c++)我会收到一个 UnsatisfiedLinkError 检索我的方法。 c++中有什么变化吗?谢谢。
【解决方案2】:

除非您从 Java 加载共享库或修改您的 Java 代码以利用 some kindIPC,否则您无法以跨平台方式执行此操作。如果你只关心 Windows,你可以abuse SetWindowsHookEx 来完成你的目标,或者使用CreateRemoteThread 函数在现有的 JVM pid 上删除一个新线程。

【讨论】:

  • CreateRemoteThread 技巧需要 LoadLibrary 地址作为入口点。你并没有真正结束一个新线程。
猜你喜欢
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 2021-02-11
  • 2011-10-15
  • 2018-05-26
相关资源
最近更新 更多