使用JNI时出现的Javah错误

44

命令:

javah -jni JavaHowTo

结果:

error: cannot access JavaHowTo 
class file for JavaHowTo not found

javadoc: error - Class JavaHowTo not found.
Error: No classes were specified on the command line.  Try -help.

我已经正确设置了类路径,但仍然遇到了javah错误。

希望能提供任何解决方案。

14个回答

82

请尝试

javah -jni com.example.JavaHowTo

其中 com.example 是你的包名。

你还需要从包含 com/example/JavaHowTo.class 的目录中运行 javah 命令。

例如,如果你的结构是:

/home/user/com/example/JavaHowTo.class

从哪里运行javah

/home/user

1
如果考虑良好的实践,头文件应该放在哪里? - basickarl
这对我有效。我已经尝试过使用-classpath并提供我的类路径,但它显示未指定任何类。只需运行javah -jni <classfile>即可。 - shailesh

13
以下方法适用于我(Win7):
javah -classpath bin/classes -jni -d jni com.my.javaclass
我从应用程序主目录运行此代码。
问题出现在子目录classes中。

在Linux下,将子目录“classes”添加到“bin”下对我有用。 - Bamerza
对我有用。我在-d之前添加了“javah -classpath bin/classes”,然后它编译了! - Vaibhav Jani

11

我每天都在我的构建脚本中使用javah并成功地使用以下选项:

javah -d <outputdir> -classpath <classpath> <fully_qualified_class>

其中:

'outputdir'是放置生成的头文件的目录

'classpath'包含一个绝对路径,指向包含您的根包的目录(如Glen所述)

'fully_qualified_class'是包含本机方法的类名,不带.class扩展名

-jni选项不是必需的(默认设置)

无论如何,您都应该检查是否已生成类文件:非常惊讶您也收到javadoc错误信息...


@dilig0 如果找不到 .class 文件,我也会遇到 javadoc 错误。也许 javah 使用 javadoc 将注释添加到 .h 文件中。 - Glen
错误已解决。我更改了环境变量,现在它运行正常。谢谢朋友们。 - krishnakumar
我有一个类似的问题 - 我有一个类,它在包层次结构中位于包含本地函数的类下面,但是 javah 找不到该类,即使在 Eclipse 中包名称也没有问题。有什么建议可以如何操作类路径来解决这个范围问题吗? - sparkFinder
1
@krishnakumar,最初设置的环境变量是什么,你又将它们更改为了什么? - Alan

9

我遇到了相同的错误,使用http://www.inonit.com/cygwin/jni/helloWorld/header.html链接,我成功地生成了.h文件。我使用了以下命令:

C:\Program Files\Java\jdk1.6.0_21\bin>javah -d C:\Prachi\Android\Workspace_QP_re
structure\HelloWorld\bin\example\jni -classpath C:\Prachi\Android\Workspace_QP_r
estructure\HelloWorld\bin example.jni.HelloWorld

这里的example.jni是我的包名,C:\Prachi\Android\Workspace_QP_restructure\是我的eclipse工作空间路径。

希望这能帮到你。


对于我来说,我必须从eclipse项目目录中执行以下操作:'javah -d jni -classpath bin/classes example.jni.HelloWorld' - Chris

4

当我将源代码目录添加到-classpath时,我遇到了这个问题。我以为类是在*.java文件中的 ;)

Javah处理的是字节码,所以你必须将包含二进制文件的目录添加到classpath

我创建了一些Eclipse任务:

"位置"

${env_var:JAVA_HOME}\bin\javah.exe

"参数"

-verbose 
-force
-classpath ;${project_loc}\bin
-d ${project_loc}\jni 
${java_type_name}

选择文件并运行

3
在我的案例中,问题相当愚蠢。 我尝试: javah com.aaa.bbb.ClassName.class 没有 ".class",我正确地生成了.h文件。 javah com.aaa.bbb.ClassName

3

I am using Eclipse.

Command syntax:

javah -d <outputdir> -classpath <classpath> <fully_qualified_class>
outputdir - 生成头文件的目录。 classpath - 包含根包所在目录的绝对路径。 fully_qualified_class - 包含本地方法的类名,不带.class扩展名。
生成以下文件:

C:\Users\John\workspace\JNITest\bin\com\canessa\john\jnitest\com_canessa_john_jnitest_CallMyCLib.h

生成的头文件内容:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_canessa_john_jnitest_CallMyCLib */

#ifndef _Included_com_canessa_john_jnitest_CallMyCLib
#define _Included_com_canessa_john_jnitest_CallMyCLib
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_canessa_john_jnitest_CallMyCLib
 * Method:    helloInC
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_canessa_john_jnitest_CallMyCLib_helloInC
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

我通过使用-classpath指向源文件目录并给出包和包含native关键字的Java文件名(即javah需要能够像jdk编译它们一样使用这些文件)来使其工作。 classpath关键字应该指向源文件夹,而不是bin文件夹...然后您应该给出包路径以及包含native关键字的类。进入src文件夹并运行javah和packageName和ClassFileName是行不通的。(这可能是因为需要获取所有Java文件。这对我有用...) - ilke Muhtaroglu

2

For Windows...

FILE DETAILS

javaFileName: HelloWorld.java
packageCode: "package com.accessibility;"
importCode: "import com.accessibility.HelloWorld;"
javaFileLocation: "S:\Accessibility\tools\src\test\java\com\accessibility\HelloWorld.java"

javaFileLocation应被视为具有两个部分...
classpath: "S:\Accessibility\tools\src\test\java"
relativeFilePath: "com\accessibility\HelloWorld.java"

创建类文件

下面的第二行命令是在Windows命令提示符下运行的。

{javacLocation} -d {ouputDirectory} {javaFileLocation}
"C:\Program Files\Java\jdk1.6.0_26\bin\javac.exe" -d "S:\Accessibility\tools\src\test\java" "S:\Accessibility\tools\src\test\java\com\accessibility\HelloWorld.java"

这将创建HelloWorld.class文件。

classFileName: HelloWorld.class 
classFileLocation: "S:\Accessibility\tools\src\test\java\com\accessibility\HelloWorld.class"

创建头文件

下面的第二行是从Windows命令提示符中运行的。

{javahLocation} -o {outputFile} -classpath {classpath} {importName}
"C:\Program Files\Java\jdk1.6.0_26\bin\javah.exe" -o "S:\Accessibility\tools\src\test\java\com\accessibility\HelloWorld.h" -classpath "S:\Accessibility\tools\src\test\java" com.accessibility.HelloWorld

这将创建 HelloWorld.h 文件。
classFileName: HelloWorld.h
classFileLocation: "S:\Accessibility\tools\src\test\java\com\accessibility\HelloWorld.h"

2

我遇到了类似的问题,并使用了-verbose选项。我不得不在classpath选项前面加上一个分号。

C:\Projects\HelloWorld\src>javah -verbose -classpath c:\projects\HellowWorld\build\classes helloworld.HelloWorld
error: cannot access helloworld.HelloWorld
class file for helloworld.HelloWorld not found
javadoc: error - Class helloworld.HelloWorld not found.
[ Search Path: c:\jdk\jre\lib\resources.jar;c:\jdk\jre\lib\rt.jar;c:\jdk\jre\lib    \sunrsasign.jar;c:\jdk\jre\lib\jsse.jar;c:\jdk\jre\lib\jce.jar;c:\jdk\jre\lib\ch    arsets.jar;c:\jdk\jre\classes\c:\projects\HellowWorld\build\classes ]
Error: No classes were specified on the command line.  Try -help.

C:\Projects\HelloWorld\src>javah -verbose -classpath ;c:\projects\HellowWorld\build\classes helloworld.HelloWorld
[ Search Path: c:\jdk\jre\lib\resources.jar;c:\jdk\jre\lib\rt.jar;c:\jdk\jre\lib\sunrsasign.jar;c:\jdk\jre\lib\jsse.jar;c:\jdk\jre\lib\jce.jar;c:\jdk\jre\lib\charsets.jar;c:\jdk\jre\classes\;c:\projects\HellowWorld\build\classes ]
[Creating file helloworld_HelloWorld.h]
[search path for source files: .,c:\projects\HellowWorld\build\classes]
[search path for class files: c:\jdk\jre\lib\resources.jar,c:\jdk\jre\lib\rt.jar,c:\jdk\jre\lib\sunrsasign.jar,c:\jdk\jre\lib\jsse.jar,c:\jdk\jre\lib\jce.jar,c:\jdk\jre\lib\charsets.jar,c:\jdk\jre\classes,c:\jdk\jre\lib\ext\dnsns.jar,c:\jdk\jre\lib\ext\localedata.jar,c:\jdk\jre\lib\ext\sunjce_provider.jar,c:\jdk\jre\lib\ext\sunmscapi.jar,c:\jdk\jre\lib\ext\sunpkcs11.jar,.,c:\projects\HellowWorld\build\classes]
[loading .\helloworld\HelloWorld.class]
[loading java\lang\Object.class(java\lang:Object.class)]
[loading java\lang\Throwable.class(java\lang:Throwable.class)]
[loading java\lang\Class.class(java\lang:Class.class)]
[done in 409 ms]

如果没有分号,这将是搜索路径的末尾: c:\jdk\jre\classes\c:\projects\HellowWorld\build\classes

由于上面的示例,我能够做到这一点。


1

Cygwin问题:

javah在Cygwin终端中无法正常工作:

$ cd /cygdrive/c/Workspace/prj/bin
$ ls com/example/JavaHotTo.class
com/example/JavaHotTo.class
$ javah com.example.JavaHowTo
Error: Could not find class file for 'com.example.JavaHowTo'.

但是使用选项-classpath .它可以完美地工作。

$ javah -classpath . com.example.JavaHowTo
$ ls *.h
com_example_JavaHotTo.h

更多技巧:
  • 选项-jni默认启用,因此不需要。
  • 您可以提供相对/绝对的classpath
  • 但是,在MS-Windows上,javah更喜欢路径à laC:\Workspace\prj\bin
  • 使用cygpath -w /cygdrive/c/Workspace/prj/bin将其转换为MS-Windows格式
  • 使用选项-d your/jni/headers/path将头文件写入另一个目录
  • javah如果不存在,则创建路径your/jni/headers/path(请参见下文)

    $ javah -d jni/headers -classpath . com.example.JavaHowTo
    $ ls       jni\headers
    com_example_JavaHotTo.h
    $ javah -d jni\path -classpath . com.example.JavaHowTo
    $ ls       jni\path
    com_example_JavaHotTo.h
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接