I'm trying to experiment with using the JNI and JDK 9. I have a class NativeTest.java
that looks like this:
public class NativeTest {
static {
System.loadLibrary("hello");
}
private native void sayHello();
public static void main(String[] args) {
new NativeTest().sayHello();
}
}
I compile the class, then use javah NativeTest
to generate the header file.
Upon issuing javah
, I get this warning:
Warning: The javah tool is planned to be removed in the next major
JDK release. The tool has been superseded by the '-h' option added
to javac in JDK 8. Users are recommended to migrate to using the
javac '-h' option; see the javac man page for more information.
I know it'll be quite a while before the next major JDK release, but I figured I'd start getting used to this new option now.
So upon trying javac -h NativeTest.java
(and other variations like NativeTest
, NativeTest.class
, etc.) I keep getting this error:
javac: no source files
I haven't been able to find any help online, probably because this feature is relatively new, and I can't find anything about this new -h
option in the man page.
Anyone else try this yet? What am I missing?
Description. The javac command reads source files that contain module, package and type declarations written in the Java programming language, and compiles them into class files that run on the Java Virtual Machine. The javac command can also process annotations in Java source files and classes.
No, java programs are not automatically compiled every time they run. Java programs must be explicitly compiled before they can be executed.
There are two ways to specify source files to javac: For a small number of source files, you can list their file names on the command line. For a large number of source files, you can use the @filenameoption on the command line to specify an argument filethat lists their file names.
javac[options] [sourcefiles-or-classnames] options Command-line options. sourcefiles-or-classnames Source files to be compiled (for example, Shape.java) or the names of previously compiled classes to be processed for annotations (for example, geometry.MyShape).
The javaccommand can also process annotationsin Java source files and classes. Source files must have a file name extension of .java. Class files have a file name extension of .class. Both source and class files normally have file names that identify the contents.
The order of source files specified on the command line or in an argument file is not important. javacwill compile the files together, as a group, and will automatically resolve any dependencies between the declarations in the various source files.
The solution I discovered was that I was not specifying the directory where javac
should place the header files.
Executing javac -h . NativeTest.java
worked.
In Java 8, you had to make intermediate step of generating class files to get C headers
Lets say you have following structure
recipeNo001
├── Makefile
├── README.md
├── c
│ └── recipeNo001_HelloWorld.c
├── java
│ └── recipeNo001
│ └── HelloWorld.java
├── lib
└── target
In Java (prior to JDK 9) you had to compile class and use javah with compiled sources
> export JAVA_HOME=$(/usr/libexec/java_home -v 1.8.0_11)
> ${JAVA_HOME}/bin/javac -d target java/recipeNo001/*.java
> ${JAVA_HOME}/bin/javah -d c -cp target recipeNo001.HelloWorld
# -d c -> put generated codes inside c directory
# -cp target -> compiled classes are inside target dir
In Java 9 you can use javac -h
with Java source code
> export JAVA_HOME=$(/usr/libexec/java_home -v 9)
> ${JAVA_HOME}/bin/javac -h c java/recipeNo001/HelloWorld.java
# -h c -> create header file inside c directory
The javah tool has been superseded by the "javac -h" feature . we should be able to just use the normal Java compiler (with the -h flag in Java 8+) to output those files during the Java compilation step.
Usage: -h directory Specifies where to place generated native header files.
When you specify this option, a native header file is generated for each class that contains native methods or that has one or more constants annotated with the java.lang.annotation.Native annotation. If the class is part of a package, then the compiler puts the native header file in a subdirectory that reflects the package name and creates directories as needed.
javac -h directory name NativeTest.java will solve the problem
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With