Skip to content

nikomoravec/AeroJet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Tests

Aero Jet - Java AOT Compiler (WIP)

A bit of history

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

What is done already

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:

libAeroJet is also able to read Java classes from JAR archives.

Build Instructions

  1. Clone AeroJet project with dependencies via git clone --recurse-submodules https://github.com/nikitamiroshnichenko/AeroJet.git
  2. Navigate to the AeroJet folder you just clone cd AeroJet
  3. Create build folder mkdir .build
  4. Navigate to the .build directory with cd .build command
  5. Run cmake ..
    1. Optionally you can provide additional cmake or AeroJet build options (see Build Options)
  6. Build AeroJet with command cmake --build . --target AeroJet

Build Options

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.

Example

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!