34

I am trying to create a header file using javah tool from command line on windows 7 OS but i am failing all the time.

I have followed different ways and even read the documentation of javah tool from oracle but they didn't help to overcome with this problem.

My class file (hellojni.class) and java file (hellojni.java) both are in the root of D:\ drive.

But whenever I run javah tool it gives me an error:

could not find class file for hellojni

I tried by providing classpath as well but not getting any header file.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
S.S Sahota
  • 341
  • 1
  • 3
  • 3

7 Answers7

115

I suspect the issue is that your class has a package and you are trying to run the command from the directory with the class file instead of the package root.

Samhain's example works because his MyClass.java contains no package, whereas I suspect yours does.

For example, assume we have the following file at c:\src\com\example\MyClass.java

package com.example;

public class MyClass {
    public native void myMethod();
}

Go to the command line and execute the following:

c:\src\com\example>javac MyClass.java

c:\src\com\example>dir

 Directory of C:\src\com\example

2015-02-23  03:17 PM    <DIR>          .
2015-02-23  03:17 PM    <DIR>          ..
2015-02-23  03:20 PM               219 MyClass.class
2015-02-23  03:17 PM                84 MyClass.java

c:\src\com\example>javah MyClass
Error: Could not find class file for 'MyClass'.

c:\src\com\example>cd c:\src

c:\src>javah com.example.MyClass

c:\src>dir
 Directory of C:\src

2015-02-23  03:18 PM    <DIR>          .
2015-02-23  03:18 PM    <DIR>          ..
2015-02-23  03:16 PM    <DIR>          com
2015-02-23  03:18 PM               449 com_example_MyClass.h

Success!

hendalst
  • 2,957
  • 1
  • 24
  • 25
16

I also faced the same problem when trying to compile and generate the C/C++ header in two steps for a Java Native Interface (JNI) implementation (I suspect that is what your trying to do from the file names). What solved it for me was to merge the two steps into one using the following command:

javac YOUR_CLASS_FILE_NAME.java -h .

The dot (.) includes the current path. This command can only be run as of Java 8.

Abdel Aleem
  • 667
  • 10
  • 15
  • 1
    Guys, make note of dot (.). I was missing dot(.). Thanks for pointing out. Saved a lot of time. – SeeTheC Nov 18 '19 at 09:56
7

javah -classpath path_to_jars_or_classes com.my.package.MyClass.

If you run with -verbose, javah -verbose -classpath path_to_jars_or_classes com.my.package.MyClass, it will show you the Search Path that it is using to locate your classes. You can use that to validate if your directory, D:\, is listed.

See javah Documentation

Example: File is named MyClass.java, internal class name is MyClass. No errors.

C:\>more MyClass.java
public class MyClass
{
   public static void doSomething(int b)
   {
      return;
   }
}

C:\>javac MyClass.java

C:\>javah -classpath C:\ MyClass

C:\>dir *.h
 Volume in drive C has no label.
 Volume Serial Number is XXXX-XXXX

 Directory of C:\

10/07/2013  11:46 AM               242 MyClass.h
               1 File(s)            242 bytes
               0 Dir(s)  X bytes free
Samhain
  • 1,767
  • 1
  • 12
  • 20
  • Thank you Samhain for yours reply. According to yours reply the command i have tried is **d:\>javah -verbose -classpath d:\ hellojni**. But still got the same error. Actually my class file and java file both are in the root of 'd' drive so i think i can't do like **com.my.package.myclass**. If possible could you post the exact command please. Thank you. – S.S Sahota Oct 05 '13 at 11:31
  • I have tried the way you posted. But still it is giving me a same error. If it is possible i can send you the screenshot as well. Is it possible we can make check where **javah** is looking for class files. – S.S Sahota Oct 07 '13 at 22:03
  • @S.SSahota post a listing of the files present on your D:\, a small sample of your .java file(mainly the class declaration), and the output from javah with -verbose. – Samhain Oct 08 '13 at 12:21
  • I have got some other directories but files are **HelloJNI.class** and **HelloJNI.java**. The code in **HelloJNI.java** is `public class HelloJNI { static { System.loadLibrary("hello"); } private native void sayHello(); public static void main(String[] args) { new HelloJNI().sayHello(); } }` When i tried **javah -verbose hellojni** i got the same error. When i tried **javah -verbose -classpath d:\ hellojni** i got the same error. – S.S Sahota Oct 08 '13 at 15:26
  • 1
    @S.SSahota Your classname is HelloJNI, not hellojni. The commandis case sensitive. – Samhain Oct 08 '13 at 16:26
  • Thank you very much Samhain. it did work and i am surprised it is case sensitive command. **javah** documentation should mention this point. – S.S Sahota Oct 08 '13 at 20:35
  • that verbose thing didnt work in my case. With or without verbose, the error message is exact same. Wasted my time :( – Shirish Herwade Mar 19 '15 at 10:44
3

I had such problem on Ubuntu 20.04 with Java 8 and Java 11 installed (and default):

$ javac -cp target/classes -d target/classes src/main/java/jni/JNIClass.java
$ javah -cp target/classes -d lib/ jni.JNIClass
Error: Could not find class file for 'jtni.JNIClass'.

It appeared, that javac was pointing to Java 11 implementation, but javah still pointed to Java 8, because javah is not included in Java 11 anymore.

Solution for Java 11 is to use javac and request it to generate header file:

$ javac -cp target/classes -h lib/ src/main/java/jni/JNIClass.java
valdisvi
  • 53
  • 3
1

Suppose your class file is in D:/A folder cd your command prompt to folder A and run below command

D:/A>javah -classpath . classfilename

Here . will set the classpath to current directory and javah tool should be able to find your class file.

Pratap Singh
  • 4,607
  • 1
  • 22
  • 24
1

On MacOS X, it required the classpath variable. This might be the solution if it can be verified on other platforms as well.

$ javah -verbose Article.HelloJNICpp
$ javah -verbose -classpath ./ Article.HelloJNICpp
[Creating file RegularFileObject[Article_HelloJNICpp.h]]
$ 
Rock
  • 177
  • 3
  • 11
1

If you are using eclipse: append -classpath PATH_OF_PACKAGE_TOP into javah CLASSNAME

Example:javah -classpath . com.byf.test.JNI

my tree : `
.
├── com
│   └── byf
│       └── test
│           └── JNI.java
└── libcall.so`


result:`
    byf@byf-Ubuntu:~/code/workspace_eclipse_java/JAVA_YF/src$ javah -classpath . com.byf.test.JNI
    byf@byf-Ubuntu:~/code/workspace_eclipse_java/JAVA_YF/src$ ls
    com  com_byf_test_JNI.h  libcall.so
    byf@byf-Ubuntu:~/code/workspace_eclipse_java/JAVA_YF/src$ cat com_byf_test_JNI.h 
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_byf_test_JNI */

    #ifndef _Included_com_byf_test_JNI
    #define _Included_com_byf_test_JNI
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_byf_test_JNI
     * Method:    add
     * Signature: (II)I
     */
    JNIEXPORT jint JNICALL Java_com_byf_test_JNI_add
      (JNIEnv *, jclass, jint, jint);

    #ifdef __cplusplus
    }
    #endif
    #endif
    `