Aero Jet - Java AOT Compiler (WIP)
In year 2019 the Java World has fall into darkness because Excelsior JET project has gone into nowhere. Java Community loosed possibility to build native applications from Java code.
Since these days I'm thinking about resurrecting of native AOT compilation of Java byte code
At the beginning AeroJet project aims to build AOT compiler for Java Bytecode up to Java Class Major Version 52 (Java 8).
According to JVM specification libAeroJet is able to read the following Java Class Structures:
- Class File
- Constant Pool
- Fields
- Methods
- Attributes
- ConstantValue
- Code
- StackMapTable
- Exceptions
- InnerClasses
- EnclosingMethod
- Synthetic
- Signature
- SourceFile
- SourceDebugExtension
- LineNumberTable
- LocalVariableTable
- LocalVariableTypeTable
- Deprecated
- RuntimeVisibleAnnotations
- RuntimeInvisibleAnnotations
- RuntimeVisibleParameterAnnotations
- RuntimeInvisibleParameterAnnotations
- RuntimeVisibleTypeAnnotations
- RuntimeInvisibleTypeAnnotations
- AnnotationDefault
- BootstrapMethods
- MethodParameters
libAeroJet is also able to read Java classes from JAR archives.
- Clone AeroJet project with dependencies via
git clone --recurse-submodules https://github.com/nikitamiroshnichenko/AeroJet.git
- Navigate to the AeroJet folder you just clone
cd AeroJet
- Create build folder
mkdir .build
- Navigate to the
.build
directory withcd .build
command - Run
cmake ..
- Optionally you can provide additional cmake or AeroJet build options (see Build Options)
- Build AeroJet with command
cmake --build . --target AeroJet
CMAKE_DISABLE_TESTING=ON|OFF
- If set to ON
- no tests will be included to the project.
CMAKE_BUILD_TYPE=Debug|Release|MinSizeRel|RelWithDebInfo
- For more information - see this page
CMAKE_INSTALL_PREFIX=/my/install/prefix
- - For more information - see this page
AEROJET_SHARED=ON|OFF
- If set to ON
- AeroJet libraries will be compiled as shared libs.
Here is simple program that prints given java class methods and their bytecode :)
#include "AeroJet.hpp"
#include "fmt/format.h"
#include <filesystem>
#include <fstream>
int main(int argc, char** argv)
{
if (argc < 2)
{
fmt::print("usage: ./SimpleClassPrinter /path/to/some/java/class");
return 1;
}
std::filesystem::path classFilePath = argv[1];
std::ifstream fileStream(classFilePath);
if (!fileStream.is_open())
{
fmt::print("Failed to open file '{}'", classFilePath.string());
return 1;
}
auto classInfo = AeroJet::Stream::Reader::read<AeroJet::Java::ClassFile::ClassInfo>(fileStream, AeroJet::Stream::ByteOrder::INVERSE);
const auto& constantPool = classInfo.constantPool();
fmt::print("ClassFile {}\n", classFilePath.string());
fmt::print("\tMethods:\n");
const std::vector<AeroJet::Java::ClassFile::MethodInfo>& classMethods = classInfo.methods();
for (const auto& methodInfo : classMethods)
{
const std::string methodName = constantPool[methodInfo.nameIndex()].as<AeroJet::Java::ClassFile::ConstantPoolInfoUtf8>().asString();
fmt::print("\t\t{}\n", methodName);
const std::vector<AeroJet::Java::ClassFile::AttributeInfo>& methodAttributes = methodInfo.attributes();
auto codeAttributeIt = std::find_if(methodAttributes.begin(), methodAttributes.end(),
[&constantPool](const AeroJet::Java::ClassFile::AttributeInfo& attributeInfo)
{
return AeroJet::Java::ClassFile::Utils::AttributeInfoUtils::extractName(constantPool, attributeInfo) == AeroJet::Java::ClassFile::Code::CODE_ATTRIBUTE_NAME;
});
if (codeAttributeIt != methodAttributes.end())
{
fmt::print("\t\t\tCode:\n");
AeroJet::Java::ClassFile::Code codeAttribute{constantPool, *codeAttributeIt};
for (const auto& instruction : codeAttribute.code())
{
fmt::print("\t\t\t\t{:#04x}\n", static_cast<AeroJet::u1>(instruction.opCode()));
}
}
}
}
For more examples - see Examples page!