【问题标题】:java.lang.NoClassDefFoundError:java.lang.NoClassDefFoundError:
【发布时间】:2014-07-08 13:38:17
【问题描述】:

您好,我正在编写一个 c++ 代码来从 .jar 类调用 java 函数。

这里是:

#include <jni.h>
int main()
{
JavaVMOption options[1];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass JCTerminalClass;
jmethodID mid;
jobject obj;
char op0[] = "-Djava.class.path=C:\\Users\\DMNX1594\\Downloads\\jcop\\jcop/offcard.jar";
options[0].optionString =op0; 
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;

status = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

if (status != JNI_ERR)
{
JCTerminalClass = env->FindClass("JCTerminal");
jthrowable exc;
exc = env->ExceptionOccurred();
if (exc) 
{
jclass newExcCls;
env->ExceptionDescribe();
env->ExceptionClear();
}

if(JCTerminalClass !=0)
{
mid = env->GetMethodID(JCTerminalClass, "com.ibm.jc.JCTerminal()", "()V");
      // Call here instance function later ...
} 
.
.
.
jvm->DestroyJavaVM();
return 0;
} else
return -1;
}

编译顺利,但在执行过程中,我得到以下信息:

java.lang.NoClassDefFoundError: JCTerminal 引起:java.lang.ClassNotFoundException:JCTerminal at java.net.URLClassLoader$1.run(URLClassLoader.java:372) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.security.AccessController.doPrivileged (本机方法) 在 java.net.URLClassLoader.findClass(URLClassLoader.java:360) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:424) 在 sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 在 java.lang.ClassLoader.loadClass(ClassLoader.java:357)

我已经尝试从我创建的 .jar 中调用简单的静态 java 函数并且它有效! 代码很像这个。

我尝试将 CLASSPATH 环境变量设置为 C:\path\to\jarFile\offcard.jar,因为我读到 NoClassDefFoundError 发生在编译过程中找到类时而不是在执行过程中......

可能是线程问题?

哦,这是我的编译命令: g++ -D __int64="long long" -I"C:\Program Files\Java\jdk1.8.0_05\include" -I"C:\Program Files\Java\jdk1.8.0_05\include\win32" -L" C:\Program Files\Java\jdk1.8.0_05\jre\bin\server" -L"C:\Program Files\Java\jdk1.8.0_05\lib" -o jni jni.cpp -ljvm

谢谢你stackoverflowers :)

【问题讨论】:

  • 你确定类路径不是-cp吗?
  • 你的意思是在编译命令中? -cp 用于java编译...
  • 这也是java命令的参数。
  • 很抱歉,我没有正确理解您的第一条评论。你到底在暗示什么?谢谢!
  • 没关系,我检查了文档 - 您使用了正确的选项

标签: java java-native-interface


【解决方案1】:

您的代码似乎在 JCTerminalClass = env-&gt;FindClass("JCTerminal"); 上失败

JNIEnv->FindClass 的文档是这样说的:

jclass FindClass(JNIEnv *env, const char *name);

[...]

name 参数是完全限定的类名或数组类型 签名 。例如,完全限定的类名 java.lang.String 类是:"java/lang/String"

但是,您只是传递了字符串 "JCTerminal" 而没有任何包名。稍后在您的示例中,您会在类名之前显示包名:"com.ibm.jc.JCTerminal()" 但是在 JNI 代码中,包名称分隔符不是点 (.) 而是斜线 (/),如上面的文档中所示。所以你需要传递给 FindClass 方法的是"com/ibm/jc/JCTerminal":

JCTerminalClass = env->FindClass("com/ibm/jc/JCTerminal");

【讨论】:

  • 你最终是对的,我只是忘记将我的 .class 文件放在正确的目录中!我只复制了 .class 而不是目录树中它之前的文件夹!谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多