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.
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_HOMEenvironment variable is defined and points to the JDK 8 installation (e.g.,
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
JDK7environment 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_HOMEenvironment 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++ --versionreport consistent versions. You may have to alter your PATH to pick the right version, especially on a Mac for which a version of
Clangcomes bundled with the command line developer tools. If your clang binary is named
clang++-VERSION, then you must define its version with the
CLANG_VERSIONenvironment variable. For example, if you are running
clang++-5.0then you should set
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 pullso that
jdk/src.zipis 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
tests/isolated contains unit tests for translations from Java to LLVM IR. The JUnit test suite compiles and runs these programs with both
jlang, then compares the results.
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 cupcommand 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.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.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!