【问题标题】:FindClass returns null when .class is not in a default package当 .class 不在默认包中时,FindClass 返回 null
【发布时间】:2018-12-06 14:35:54
【问题描述】:

我刚刚查看了其他人的问题,但似乎没有人遇到与我相同的问题。我有一个启动另一个 java 应用程序的 Java 类 HelloWorldHandler.java(在 org.eclipse.gemoc.testapplilauncher 项目中的 org.eclipse.gemoc.testapplilauncher.handlers 包中)。然后我有一个c文件launcherC.c(在同一个项目但不同的目录中)应该通过JNI调用java文件中的execute方法。现在,我以前的所有 JNI 应用程序都可以正常工作,而这个没有。唯一的区别是 HelloWorldHandler.java 不在默认包中(因此 .class 不是直接在 /bin 中)并且有多个包导入(可能会随着 FindClass 调用(?)而改变)。 我使用
gcc -fPIC -I"/usr/lib/jvm/java-8-oracle/include" -I"/usr/lib/jvm/java-8-oracle/include/linux" -L/usr/lib/jvm/java-8-oracle/lib/amd64/jli/ -L/usr/lib/va-8-oracle/jre/lib/amd64/server/ -o launcherC launcherC.c -ljli -ljvm

启动 c 文件

export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/usr/lib/jvm/java-8-oracle/jre/lib/amd64/server/

没有问题。但是当我执行它时,它什么也没做,没有任何期望和错误。我检查了一下,FindClass 返回 NULL。

HelloWorldHandler.java

package org.eclipse.gemoc.testapplilauncher.handlers;


public class HelloWorldHandler {
    @Execute
    public static void execute() {

        ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();

        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        IFile ff = root.getFile(new Path("d/Test.launch"));


        ILaunchConfiguration res = manager.getLaunchConfiguration(ff);
        DebugUITools.launch(res, ILaunchManager.DEBUG_MODE);

    }
}

launcherC.c

#include <jni.h>
#include <string.h>

int main()
{
    JavaVMOption options[1];
    JNIEnv *env;
    JavaVM *jvm;
    JavaVMInitArgs vm_args;
    long status;
    jclass cls;
    jmethodID mid;

    options[0].optionString = "-Djava.class.path=/home/ezambon/Desktop/modeling/org/eclipse/gemoc/testAppliLauncher/bin/org/eclipse/gemoc/testapplilauncher/handlers";
    memset(&vm_args, 0, sizeof(vm_args));
    vm_args.version = JNI_VERSION_1_2;
    vm_args.nOptions = 1;
    vm_args.options = options;
    status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

    if (status != JNI_ERR)
    {
        cls = (*env)->FindClass(env, "HelloWorldHandler");

        if(cls != 0) {
        //printf("asdfgh\n");
        mid = (*env)->GetStaticMethodID(env, cls, "execute", "()V");

        if(mid !=0) {
             (*env)->CallStaticVoidMethod(env, cls, mid);
        }
    }
    //printf("qwerty");
    (*jvm)->DestroyJavaVM(jvm);
    return 0;
  }
  else
    return -1;
}

所有的建议都非常受欢迎,我快疯了。谢谢你:)

【问题讨论】:

  • 处理程序中的代码只会在正确设置的 Eclipse 中的 Eclipse 插件中运行。它将不会在空的 JVM 中运行,如您在此处显示的那样。
  • 那么,要让 JNI 成为可能,我应该怎么做?
  • 你不能像这样运行 Eclipse 插件代码。最接近的是创建一个“无头”Eclipse RCP 并运行可执行文件。

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


【解决方案1】:

你设置类路径错误的第一个问题

代替

options[0].optionString = "-Djava.class.path=/home/ezambon/Desktop/modeling/org/eclipse/gemoc/testAppliLauncher/bin/org/eclipse/gemoc/testapplilauncher/handlers";

你应该有

options[0].optionString = "-Djava.class.path=/home/ezambon/Desktop/modeling/org/eclipse/gemoc/testAppliLauncher";

你应该使用完整的类名

cls = (*env)->FindClass(env, "org.eclipse.gemoc.testapplilauncher.handlers.HelloWorldHandler");

但我想这不是你的全部问题。

【讨论】:

  • 我试过了,还是不行。 cls 仍然为 NULL。唯一的问题在于路径,因为其余代码与我制作的其他程序相同,并且都可以工作。
  • 在合格的类名org/eclipse/...中使用斜杠(不是句点)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 2021-08-28
  • 2023-03-26
  • 1970-01-01
相关资源
最近更新 更多