Java Tools Tutorials - Herong's Tutorial Examples - v6.24, by Herong Yang
jaotc - Java Ahead-Of-Time Compiler
This chapter provides provides a tutorial example on how to use 'jaotc' command to produce native code in the form of a shared library from Java bytecode files. But I didn't find any way to use the shared library.
Warning: "jaotc" has been removed since JDK 17.
What Is "jaotc"? - "jaotc" is a Java Ahead-Of-Time (AOT) static compiler which produces native code in the form of a shared library from Java bytecode files.
According to Java documentation, "The Java Virtual Machine can load these shared libraries and use native code from them when corresponding Java methods are called. By using jaotc, there is no need to wait for the JIT compiler to generate (by compiling bytecode) the fast native code for these Java methods. The code is already generated by jaotc and ready to be immediately used. For the same reason, there is no need to execute these methods in the Interpreter because fast compiled native code can be executed instead."
If you have %java_home%\bin directory included in "path" the environment variable, you can run "jaotc --help" to get the usage information:
herong> jaotc --help Usage: jaotc <options> list list A : separated list of class names, modules, jar files or directories which contain class files. where options include: --output <file> Output file name --class-name <class names> List of classes to compile --jar <jarfiles> List of jar files to compile --module <modules> List of modules to compile --directory <dirs> List of directories where to search for files to compile --search-path <dirs> List of directories where to search for specified files --compile-commands <file> Name of file with compile commands --compile-for-tiered Generate profiling code for tiered compilation --compile-with-assertions Compile with java assertions --compile-threads <number> Number of compilation threads to be used --ignore-errors Ignores all exceptions thrown during class loading --exit-on-error Exit on compilation errors --info Print information during compilation --verbose Print verbose information --debug Print debug information -? -h --help Print this help message --version Version information --linker-path Full path to linker executable -J<flag> Pass <flag> directly to the runtime system
Here is what I did to try the "jaotc" tool. on my macOS computer with JDK 15.
1. Create a test class file called Circle.java:
/* Circle.java * Copyright (c) 2018 HerongYang.com. All Rights Reserved. */ public class Circle { public String uom = "Centimeter"; private int x = 0; private int y = 0; private int r = 1; public void setRadius(int radius) { r = radius; } public void setCenter(int centerX, int centerY) { x = centerX; y = centerY; } public void printRadius() { System.out.println(r + " " + uom); } public void printArea() { double area = getArea(); System.out.println(area + " " + uom + "^2"); } private double getArea() { return 3.14159*r*r; } }
2. Create another class to call methods in the Circle class:
/* CircleTest.java * Copyright (c) 2018 HerongYang.com, All Rights Reserved. */ public class CircleTest { public static void main(String[] a) { Circle c = new Circle(); c.setRadius(3); c.setCenter(1,1); c.printRadius(); c.printArea(); } }
3. Compile both class files:
herong$ javac Circle.java herong$ javac CircleTest.java herong$ ls -l -rw-r--r-- 1370 Circle.class -rw-r--r-- 602 Circle.java -rw-r--r-- 434 CircleTest.class -rw-r--r-- 260 CircleTest.java
4. Compile Circle.class into a native code library:
$ /Library/Java/JavaVirtualMachines/jdk-15.jdk/Contents/Home/bin/jaotc \ --output libCircle.so Circle.class herong$ ls -l -rw-r--r-- 1370 Circle.class -rw-r--r-- 602 Circle.java -rw-r--r-- 434 CircleTest.class -rw-r--r-- 260 CircleTest.java -rw-r--r-- 142088 libCircle.so
5. Run CircleTest with the native code library:
herong$ java -XX:+UnlockExperimentalVMOptions \ -XX:AOTLibrary=./libCircle.so CircleTest 3 Centimeter 28.274309999999996 Centimeter^2
The output looks correct. But how can we confirm that JVM actually called the native code in libCircle.so instead of the bytecode in Circle.class?
6. Let's remove Circle.class and see what happens:
herong$ rm Circle.class herong$ java -XX:+UnlockExperimentalVMOptions \ -XX:AOTLibrary=./libCircle.so CircleTest Exception in thread "main" java.lang.NoClassDefFoundError: Circle
Too bad. JVM will not start without Circle.class.
7. Let's change the method printArea() in the Circle.class and see which version of the method gets called:
herong$ vi Circle.java ... public void printArea() { double area = getArea(); System.out.println(area + " " + uom + "^2 - Changed"); } ... herong$ javac Circle.java herong$ java -XX:+UnlockExperimentalVMOptions \ -XX:AOTLibrary=./libCircle.so CircleTest 3 Centimeter 28.274309999999996 Centimeter^2 - Changed
That's really bad. JVM did not all native code in libCircle.so as instructed! It called the changed version from the bytecode in Circle.class.
So I am not able to use the native code in the shared library generated by "jaotc".
Table of Contents
javac - The Java Program Compiler
java - The Java Program Launcher
jpackage - Binary Package Builder
javadoc - The Java Document Generator
jdeps - The Java Class Dependency Analyzer
jdeprscan - The Java Deprecated API Scanner
jcmd - The JVM Diagnostic Tool
jconsole - Java Monitoring and Management Console
jstat - JVM Statistics Monitoring Tool
jhsdb - The Java HotSpot Debugger
jvisualvm (Java VisualVM) - JVM Visual Tool
javap - The Java Class File Disassembler
keytool - Public Key Certificate Tool
jrunscript - Script Code Shell
serialver - serialVersionUID Generator
►jaotc - Java Ahead-Of-Time Compiler
native2ascii - Native-to-ASCII Encoding Converter