Skip to content
JLang: Ahead-of-time compilation of Java programs to LLVM
Java C++ C Makefile Shell Assembly
Branch: master
Clone or download
dz333 Merge pull request #42 from guoyiteng/master
Support Reflection of Array Type
Latest commit 432b219 May 20, 2019

README.md

JLang

JLang supports ahead-of-time compilation of Java. It works by adding an LLVM back end to the Polyglot compiler, allowing Java to be translated down to LLVM IR. From there, a back end can translate to the architecture of choice.

Since Polyglot already translates extended Java code into vanilla Java ASTs, JLang should be interoperable with other Polyglot extensions by default. However, JLang aims to be extensible itself, so that one can write optimized LLVM translations for language extensions when needed.

A user manual and developer guide can be found on the JLang website.

Contributing

Before contributing, please do the following.

(1) Read through the rest of this README.
(2) Read through all GitHub issues carefully, to get the most up-to-date picture of the current state of the project.
(3) Read through the developer guide on the website, to get technical details on the most critical subcomponents of JLang.
(4) If you need to work on compiler translations, get familiar with LLVM IR.
(5) If you need to work on native runtime code, get familiar with JNI.

Quick start guide

JLang has the following dependencies, which you will need to download and install prior to use.

  • JDK 8 and Ant are required to build the compiler. Ant is best installed through your preferred package manager. Be sure that the JAVA_HOME environment variable is defined and points to the JDK 8 installation (e.g., /Library/Java/JavaVirtualMachines/jdk1.8.0_162.jdk/Contents/Home/).

  • JDK 7 is required to compile programs with JLang, since we target Java 7. This specific, linked version of the JDK native code is required to build the JDK source that we have provided with this repo. At the moment, no other distribution of JDK native code is compatible with this source on all platforms. Also be sure that the JDK7 environment variable is defined and points to the JDK 7 home directory. When trying to run programs compiled with JLang you will need to set the JAVA_HOME environment variable to this value as well (see the test suite Makefile for an example of how to execute JLang-compiled binaries).

  • LLVM and Clang are needed to build the runtime and create binaries from Java programs. JLang is tested with version 5.0.1, which you can download here. It may be possible to install through a package manager (e.g., sudo apt install llvm && sudo apt install clang). After installation be sure that llc --version (for example) and clang++ --version report consistent versions. You may have to alter your PATH to pick the right version, especially on a Mac for which a version of Clang comes bundled with the command line developer tools. If your clang binary is named clang++-VERSION, then you must define its version with the CLANG_VERSION environment variable. For example, if you are running clang++-5.0 then you should set CLANG_VERSION=5.0.

  • The Boehm-Demers-Weiser garbage collector is also required for creating binaries. JLang is tested with version 7.6.4, which you can download here or install through a package manager (brew install boehmgc). A typical install from source looks like this: ./configure && make && make install. Note that the garbage collector depends on libatomic_ops, which is often available through a package manager.

  • Git LFS is required to use JLang with OpenJDK 7. We use Git LFS to track a zip file containing all OpenJDK 7 Java source files. (The alternative is requiring a checkout and build of the full OpenJDK tree, which is notoriously difficult to configure.) Be sure to do a git lfs pull so that jdk/src.zip is downloaded; otherwise you will see strange error messages when trying to build.

Note that Polyglot is also required, but is tracked as a git submodule and will be built automatically.

Finally, build JLang by running make at the top level of the repository. By default this will build only a "bare-bones" JDK, which is enough to run the unit tests. Note that JLang is usually tested on OS X; see issue #55 for updates on whether the build system supports Linux.

To run the test-suite you can execute the make tests at the top level of the repository. In order to run specific tests, the test Makefile can also be run from the tests/isolated directory; however, some environment variables may not be appropriately set depending upon your operating system.

If you want to run unit tests from IntelliJ, run the TestAll class, using the top level of the repository as the working directory.

High-level project structure

  • Compiler source files are in the compiler/src/jlang directory. Most translation code resides in the extension subdirectory.

  • runtime contains Java code and native code needed to implement Java semantics at runtime (think: exceptions, JNI, reflection, etc.).

  • tests/isolated contains unit tests for translations from Java to LLVM IR. The JUnit test suite compiles and runs these programs with both javac and jlang, then compares the results.

  • jdk provides a way to compile and link OpenJDK 7 with JLang, and jdk-lite provides a "bare-bones" JDK implementation used for unit testing.

  • docs contains documentation for the various subcomponents of JLang, in the form of Markdown files. These files also provide the content for the JLang website.

  • lib contains Polyglot (the frontend for JLang); a fork of JavaCPP Presets to generate Java stubs from LLVM headers; and various supporting .jar files.

  • examples contains full Java 7 projects which can be compiled with JLang and executed. Currently, we have included only the CUP parser generator, which can be built with the make cup command in the top-level JLang dirctory and is executable with the script cup.sh.

Status (August 2018)

All translations from Java to LLVM IR are complete, with the exception of the synchronized keyword (see below on concurrency support). This means that all Java 7 language features---expressions, control flow, exceptions, method dispatch, switch statements, try-with-resources, initializer blocks, implicit type conversions, etc.---are translated robustly and as specified by the JLS. All of our unit tests pass.

However, JLang is still a work in progress for two important reasons.

(1) Full JDK support & Reflection. The JDK includes thousands of classes that are critical to the Java ecosystem, such as java.lang.Class, java.util.ArrayList, java.io.File, and java.net.Socket. Thus it is important to be able to compile programs that rely on the JDK. So far we can fully support a hand-written "bare-bones" JDK that includes only the JDK classes that are necessary for unit tests (java.lang.Object, java.lang.Class, java.lang.System, etc.). We have also supported a large number of JVM features such that many operations in the JDK are supported. Many features are still missing, but most of them have analogues that are already implemented, which means that completing these features should be straightforward. The main feature we are missing is full Reflection support; most reflection methods beyond Class.forName(String name) are unimplemented. For more details see: issue #18.

(2) Concurrency support. Support for multiple threads and synchronization has not been started, as JDK support took priority. JLang will ignore the Java synchronized keyword, and the native runtime code is generally not thread-safe. Please see issue #1 for more information.

All other loose ends (minor bugs, build system issues, etc.) are tracked as GitHub issues as well. If you would like to contribute, please read through all of these tracked issues carefully!

You can’t perform that action at this time.