【问题标题】:Trying to inject a dll into an already running JVM?试图将 dll 注入到已经运行的 JVM 中?
【发布时间】:2014-04-13 16:06:44
【问题描述】:

我在 HKEY_CLASSES_ROOT* 中创建了一个 Windows 注册表项,其值为:“C:\test.exe”“%1”,以创建一个新的右键单击上下文菜单项,将单击文件的文件路径传递给注册 test.exe。在 test.exe 中加载了一个 dll 文件,该文件应该注入到已经运行的 jvm 中以调用方法并传递文件路径。问题是 .dll 没有找到 JVM 实例,尽管它在 while 循环(原型)中运行。你能帮我解决这个问题吗?我如何访问 JVM?谢谢

.java:

public class Main
{
    public static void main(String[] args)
    {   
        while(true)
        {

        }
    }

    public static void readAndOutputFilePath(String result)
    {       
        System.out.println("Java result: "+result); 
        try
        {
            System.in.read();
        }
        catch (IOException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

.dll:

HMODULE m_hDllInstance = LoadLibrary("jvm.dll");
if( m_hDllInstance == 0)
{
    printf("The jvm.dll could not be found");
    getchar();    
}
else
    printf("jvm.dll found");


JavaVM *jvm;   
JNIEnv *env;  

typedef jint (JNICALL * GetCreatedJavaVMs)(JavaVM**, jsize, jsize*);
GetCreatedJavaVMs jni_GetCreatedJavaVMs = (GetCreatedJavaVMs)GetProcAddress(m_hDllInstance, "JNI_GetCreatedJavaVMs");

jint size = 1;
jint vmCount;

jint ret= jni_GetCreatedJavaVMs(&jvm, size, &vmCount);

cout << endl << "GetCreated: " << vmCount << endl;
getchar();

jint rc = jvm->AttachCurrentThread((void **) & env, NULL);

jclass cls = env->FindClass("Main");
jmethodID mid = env->GetStaticMethodID(cls, "readAndOutputFilePath", "(Ljava/lang/String;)V");

jstring resultString = env->NewStringUTF(path);
env->CallStaticVoidMethod(cls, mid, resultString);
...

【问题讨论】:

  • 没有其他意见?请给我一些提示,并请阅读底部的我的 cmets。非常感谢。

标签: java c++ winapi java-native-interface dll-injection


【解决方案1】:

与运行在独立、独立进程中的 Java 程序进行通信并没有什么特别之处。可以使用 Java 支持的任何 IPC 工具。首先想到的是本地套接字,还有共享内存和普通的旧文件系统。

JNI 可能无关紧要,因为您的 Java 程序位于一个单独的进程中 - 除非您想使用某些特定于 Windows 的通信模式,例如 OLE。在这种情况下,您需要用另一种语言编写通信协议并将它们加载到您的 Java 程序中。

【讨论】:

  • 感谢您的提示。我已经实现了一个带有套接字的原型并且它可以工作:) 但我想要一个没有网络通信的低延迟版本。我试过了。与共享内存/内存映射文件。但是,如果进程 1 知道进程 2 已将单击的文件路径写入共享内存,我该如何管理呢?我需要某种侦听器(轮询/事件侦听器)来告诉我新数据何时写入共享内存...
  • 127.0.0.1 上的套接字对于任何涉及 UI 的东西来说延迟足够低。
【解决方案2】:

您似乎不了解 JVM 究竟是什么。它本身就是一个加载到进程中的 DLL。它不是一个“东西”,它只是“在那里”。使用 JNI 调用 API,您可以启动一个,除非您这样做,否则您不会在自己启动的 .exe 中找到“那个”JVM。

【讨论】:

  • 您好,但在另一篇文章中,一位用户实现了这一点:link。但我不明白他是如何做到这一点的,我希望有人可以帮助我解决上述代码 sn-p 中的问题。您知道另一种将上下文菜单的文件路径放入已经运行的 JVM 的方法吗?我还考虑将文件路径传递给使用 RMI 调用已经运行的 Java 程序的方法的 Java 程序,但这对于我的问题来说太复杂和“重量级”......谢谢
  • 我认为您要做的是从本机程序启动 jvm 和您的类文件。这与注入任何代码无关。您需要首先创建一个利用 JNI 启动 JVM 的 C 可执行文件。有很多例子可以做到这一点。见:inonit.com/cygwin/jni/invocationApi/c.html
  • 还有一件事,你为什么要从上下文菜单中获取文件路径!?上下文菜单是可以由任何正在运行的应用程序创建的屏幕小部件。我的意思是,您在尝试错误地解决原始问题时遇到了问题。
  • 我原来的问题是:我有一个 Java 程序已经在运行(在后台)。我在 Windows 资源管理器上下文菜单中创建了一个菜单条目,并在 Windows 注册表中创建了一个条目(如上所述)。现在我想在我已经运行的 Java 程序中获取单击文件的文件路径,以保存一些文件信息。我怎么能做到这一点?我的注册表项:“C:\test.exe”“%1”或其他方法:java -jar“C:\test.jar”“%1”...如何将单击文件的文件路径传递给我的已经在运行 Java 程序了吗?
  • 我需要……像这样:(stackoverflow.com/questions/370114/…)。如上所述,问题是我的 Java prog.已经运行。我怎么能传递文件路径?我已经考虑过第二个 Java 程序,它可以捕获文件路径并与正在运行的程序进行通信(关于 RMI 等)。但我真的不喜欢那种解决方案...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多