[INACTIVE] Avian is a lightweight virtual machine and class library designed to provide a useful subset of Java's features, suitable for building self-contained applications.

Overview

Avian - A lightweight Java Virtual Machine (JVM)

PLEASE NOTE: This project is not currently being developed, maintained, or supported. Feel free to use and/or fork it, but any issues filed here will probably be ignored.

Build Status

Quick Start

These are examples of building Avian on various operating systems for the x86_64 architecture. You may need to modify JAVA_HOME according to where the JDK is installed on your system. In all cases, be sure to use forward slashes in the path.

on Linux:

$ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
$ make
$ build/linux-x86_64/avian -cp build/linux-x86_64/test Hello

on Mac OS X:

$ export JAVA_HOME=$(/usr/libexec/java_home)
$ make
$ build/macosx-x86_64/avian -cp build/macosx-x86_64/test Hello

on Windows (Cygwin):

$ git clone [email protected]:ReadyTalk/win64.git ../win64
$ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.7.0_45"
$ make
$ build/windows-x86_64/avian -cp build/windows-x86_64/test Hello

on FreeBSD:

$ export JAVA_HOME=/usr/local/openjdk7
$ gmake
$ build/freebsd-x86_64/avian -cp build/freebsd-x86_64/test Hello

Introduction

Avian is a lightweight virtual machine and class library designed to provide a useful subset of Java's features, suitable for building self-contained applications.

Supported Platforms

Avian can currently target the following platforms:

  • Linux (i386, x86_64, ARM, and ARM64)
  • Windows (i386 and x86_64)
  • Mac OS X (i386 and x86_64)
  • Apple iOS (i386, x86_64, ARM, and ARM64)
  • FreeBSD (i386, x86_64)

Building

Build requirements include:

  • GNU make 3.80 or later
  • GCC 4.6 or later or LLVM Clang 3.1 or later (see use-clang option below)
  • JDK 1.6 or later
  • MinGW 3.4 or later (only if compiling for Windows)
  • zlib 1.2.3 or later

Earlier versions of some of these packages may also work but have not been tested.

The build is directed by a single makefile and may be influenced via certain flags described below, all of which are optional.

$ make \
    platform={linux,windows,macosx,ios,freebsd} \
    arch={i386,x86_64,arm,arm64} \
    process={compile,interpret} \
    mode={debug,debug-fast,fast,small} \
    lzma=<lzma source directory> \
    bootimage={true,false} \
    tails={true,false} \
    continuations={true,false} \
    use-clang={true,false} \
    openjdk=<openjdk installation directory> \
    openjdk-src=<openjdk source directory> \
    android=<android source directory> \
    ios-version=<iOS minimum version>
  • platform - the target platform

    • default: output of $(uname -s | tr [:upper:] [:lower:]), normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows)
  • arch - the target architecture

    • default: output of $(uname -m), normalized in some cases (e.g. i686 -> i386)
  • process - choice between pure interpreter or JIT compiler

    • default: compile
  • mode - which set of compilation flags to use to determine optimization level, debug symbols, and whether to enable assertions

    • default: fast
  • lzma - if set, support use of LZMA to compress embedded JARs and boot images. The value of this option should be a directory containing a recent LZMA SDK (available here). Currently, only version 9.20 of the SDK has been tested, but other versions might work.

    • default: not set
  • armv6 - if true, don't use any instructions newer than armv6. By default, we assume the target is armv7 or later, and thus requires explicit memory barrier instructions to ensure cache coherency

  • bootimage - if true, create a boot image containing the pre-parsed class library and ahead-of-time compiled methods. This option is only valid for process=compile builds. Note that you may need to specify both build-arch=x86_64 and arch=x86_64 on 64-bit systems where "uname -m" prints "i386".

    • default: false
  • tails - if true, optimize each tail call by replacing the caller's stack frame with the callee's. This convention ensures proper tail recursion, suitable for languages such as Scheme. This option is only valid for process=compile builds.

    • default: false
  • continuations - if true, support continuations via the avian.Continuations methods callWithCurrentContinuation and dynamicWind. See Continuations.java for details. This option is only valid for process=compile builds.

    • default: false
  • use-clang - if true, use LLVM's clang instead of GCC to build. Note that this does not currently affect cross compiles, only native builds.

    • default: false
  • openjdk - if set, use the OpenJDK class library instead of the default Avian class library. See "Building with the OpenJDK Class Library" below for details.

    • default: not set
  • openjdk-src - if this and the openjdk option above are both set, build an embeddable VM using the OpenJDK class library. The JNI components of the OpenJDK class library will be built from the sources found under the specified directory. See "Building with the OpenJDK Class Library" below for details.

    • default: not set
  • android - if set, use the Android class library instead of the default Avian class library. See "Building with the Android Class Library" below for details.

    • default: not set
  • ios-version - the minimum iOS SDK version which will be used when compiling for ios target. Do not use a value 11.0 or larger, if you want to support 32 bit version. This option is only valid for platform=ios .

    • default: 8.0

These flags determine the name of the directory used for the build. The name always starts with ${platform}-${arch}, and each non-default build option is appended to the name. For example, a debug build with bootimage enabled on Linux/x86_64 would be built in build/linux-x86_64-debug-bootimage. This allows you to build with several different sets of options independently and even simultaneously without doing a clean build each time.

Note that not all combinations of these flags are valid. For instance, non-jailbroken iOS devices do not allow JIT compilation, so only process=interpret or bootimage=true builds will run on such devices. See here for an example of an Xcode project for iOS which uses Avian.

If you are compiling for Windows, you may either cross-compile using MinGW or build natively on Windows under Cygwin.

Installing Cygwin:

1. Download and run setup.exe from cygwin's website, installing the base system and these packages: make, gcc-mingw-g++, mingw64-i686-gcc-g++, mingw64-x86_64-gcc-g++, and (optionally) git.

You may also find our win32 repository useful: (run this from the directory containing the avian directory)

$ git clone [email protected]:ReadyTalk/win32.git

This gives you the Windows JNI headers, zlib headers and library, and a few other useful libraries like OpenSSL, libjpeg, and libpng. There's also a win64 repository for 64-bit builds:

  $ git clone [email protected]:ReadyTalk/win64.git

Building with the Microsoft Visual C++ Compiler

You can also build using the MSVC compiler, which makes debugging with tools like WinDbg and Visual Studio much easier. Note that you will still need to have GCC installed - MSVC is only used to compile the C++ portions of the VM, while the assembly code and helper tools are built using GCC.

Note that the MSVC build isn't tested regularly, so is fairly likely to be broken.

Avian targets MSVC 11 and above (it uses c++ features not available in older versions).

To build with MSVC, install Cygwin as described above and set the following environment variables:

$ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/Common7/Tools:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v3.5:/cygdrive/c/WINDOWS/Microsoft.NET/Framework/v2.0.50727:/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC/VCPackages:/cygdrive/c/Program Files/Microsoft SDKs/Windows/v6.0A/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem"
$ export LIBPATH="C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;"
$ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 11.0\VC"
$ export LIB="C:\Program Files\Microsoft Visual Studio 11.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;"
$ export INCLUDE="C:\Program Files\Microsoft Visual Studio 11.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;"

Adjust these definitions as necessary according to your MSVC installation.

Finally, build with the msvc flag set to the MSVC tool directory:

$ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 11.0/VC"

Building with the OpenJDK Class Library

By default, Avian uses its own lightweight class library. However, that library only contains a relatively small subset of the classes and methods included in the JRE. If your application requires features beyond that subset, you may want to tell Avian to use OpenJDK's class library instead. To do so, specify the directory where OpenJDK is installed, e.g.:

$ make openjdk=/usr/lib/jvm/java-7-openjdk

This will build Avian as a conventional JVM (e.g. libjvm.so) which loads its boot class library and native libraries (e.g. libjava.so) from /usr/lib/jvm/java-7-openjdk/jre at runtime. Note that you must use an absolute path here, or else the result will not work when run from other directories. In this configuration, OpenJDK needs to remain installed for Avian to work, and you can run applications like this:

$ build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \
    com.example.MyApplication

Alternatively, you can enable a stand-alone build using OpenJDK by specifying the location of the OpenJDK source code, e.g.:

$ make openjdk=$(pwd)/../jdk7/build/linux-amd64/j2sdk-image \
    openjdk-src=$(pwd)/../jdk7/jdk/src

You must ensure that the path specified for openjdk-src does not have any spaces in it; make gets confused when dependency paths include spaces, and we haven't found away around that except to avoid paths with spaces entirely.

The result of such a build is a self-contained binary which does not depend on external libraries, jars, or other files. In this case, the specified paths are used only at build time; anything needed at runtime is embedded in the binary. Thus, the process of running an application is simplified:

$ build/linux-x86_64-openjdk-src/avian -cp /path/to/my/application \
    com.example.MyApplication

Note that the resulting binary will be very large due to the size of OpenJDK's class library. This can be mitigated using UPX, preferably an LZMA-enabled version:

$ upx --lzma --best build/linux-x86_64-openjdk-src/avian

You can reduce the size futher for embedded builds by using ProGuard and the supplied openjdk.pro configuration file (see "Embedding with ProGuard and a Boot Image" below). Note that you'll still need to use vm.pro in that case -- openjdk.pro just adds additional constraints specific to the OpenJDK port. Also see app.mk in the avian-swt-examples project for an example of using Avian, OpenJDK, ProGuard, and UPX in concert.

Here are some examples of how to install OpenJDK and build Avian with it on various OSes:

Debian-based Linux:

Conventional build:

$ apt-get install openjdk-7-jdk
$ make openjdk=/usr/lib/jvm/java-7-openjdk test

Stand-alone build:

$ apt-get install openjdk-7-jdk
$ apt-get source openjdk-7-jdk
$ apt-get build-dep openjdk-7-jdk
$ (cd openjdk-7-7~b147-2.0 && dpkg-buildpackage)
$ make openjdk=/usr/lib/jvm/java-7-openjdk \
    openjdk-src=$(pwd)/openjdk-7-7~b147-2.0/build/openjdk/jdk/src \
    test

Mac OS X:

Prerequisite: Build OpenJDK 7 according to this site.

Conventional build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test

Stand-alone build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \
    openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test

Windows (Cygwin):

Prerequisite: Build OpenJDK 7 according to this site. Alternatively, use https://github.com/alexkasko/openjdk-unofficial-builds.

Conventional build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test

Stand-alone build:

$ make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \
    openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test

Currently, only OpenJDK 7 is supported. Later versions might work, but have not yet been tested.

Building with the Android Class Library

As an alternative to both the Avian and OpenJDK class libaries, you can also build with the Android class library. Now it should work on Linux, OS X and Windows.

The simpliest way to build Avian with Android classpath is to use avian-pack project: https://github.com/bigfatbrowncat/avian-pack

Avian-pack consists of Avian itself with some Android components (such as libcore and icu4c).

Note that we use the upstream OpenSSL repository and apply the Android patches to it. This is because it is not clear how to build the Android fork of OpenSSL directly without checking out and building the entire platform. As of this writing, the patches apply cleanly against OpenSSL 1.0.1h, so that's the tag we check out, but this may change in the future when the Android fork rebases against a new OpenSSL version.

Installing

Installing Avian is as simple as copying the executable to the desired directory:

$ cp build/${platform}-${arch}/avian ~/bin/

Embedding

The following series of commands illustrates how to produce a stand-alone executable out of a Java application using Avian.

Note: if you are building on Cygwin, prepend "x86_64-w64-mingw32-" or "i686-w64-mingw32-" to the ar, g++, gcc, strip, and dlltool commands below (e.g. x86_64-w64-mingw32-gcc).

1. Build Avian, create a new directory, and populate it with the VM object files and bootstrap classpath jar.

$ make
$ mkdir hello
$ cd hello
$ ar x ../build/${platform}-${arch}/libavian.a
$ cp ../build/${platform}-${arch}/classpath.jar boot.jar

2. Build the Java code and add it to the jar.

$ cat >Hello.java <<EOF
public class Hello {
  public static void main(String[] args) {
    System.out.println("hello, world!");
  }
}
EOF
 $ javac -bootclasspath boot.jar Hello.java
 $ jar u0f boot.jar Hello.class

3. Make an object file out of the jar.

$ ../build/${platform}-${arch}/binaryToObject/binaryToObject boot.jar \
     boot-jar.o _binary_boot_jar_start _binary_boot_jar_end ${platform} ${arch}

If you've built Avian using the lzma option, you may optionally compress the jar before generating the object:

  ../build/$(platform}-${arch}-lzma/lzma/lzma encode boot.jar boot.jar.lzma
     && ../build/${platform}-${arch}-lzma/binaryToObject/binaryToObject \
       boot.jar.lzma boot-jar.o _binary_boot_jar_start _binary_boot_jar_end \
       ${platform} ${arch}

Note that you'll need to specify "-Xbootclasspath:[lzma.bootJar]" instead of "-Xbootclasspath:[bootJar]" in the next step if you've used LZMA to compress the jar.

4. Write a driver which starts the VM and runs the desired main method. Note the bootJar function, which will be called by the VM to get a handle to the embedded jar. We tell the VM about this jar by setting the boot classpath to "[bootJar]".

$ cat >embedded-jar-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"
#include "stdlib.h"

#if (defined __MINGW32__) || (defined _MSC_VER)
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __attribute__ ((visibility("default"))) \
  __attribute__ ((used))
#endif

#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
#  define SYMBOL(x) binary_boot_jar_##x
#else
#  define SYMBOL(x) _binary_boot_jar_##x
#endif

extern "C" {

  extern const uint8_t SYMBOL(start)[];
  extern const uint8_t SYMBOL(end)[];

  EXPORT const uint8_t*
  bootJar(size_t* size)
  {
    *size = SYMBOL(end) - SYMBOL(start);
    return SYMBOL(start);
  }

} // extern "C"

extern "C" void __cxa_pure_virtual(void) { abort(); }

int
main(int ac, const char** av)
{
  JavaVMInitArgs vmArgs;
  vmArgs.version = JNI_VERSION_1_2;
  vmArgs.nOptions = 1;
  vmArgs.ignoreUnrecognized = JNI_TRUE;

  JavaVMOption options[vmArgs.nOptions];
  vmArgs.options = options;

  options[0].optionString = const_cast<char*>("-Xbootclasspath:[bootJar]");

  JavaVM* vm;
  void* env;
  JNI_CreateJavaVM(&vm, &env, &vmArgs);
  JNIEnv* e = static_cast<JNIEnv*>(env);

  jclass c = e->FindClass("Hello");
  if (not e->ExceptionCheck()) {
    jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
    if (not e->ExceptionCheck()) {
      jclass stringClass = e->FindClass("java/lang/String");
      if (not e->ExceptionCheck()) {
        jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
        if (not e->ExceptionCheck()) {
          for (int i = 1; i < ac; ++i) {
            e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
          }

          e->CallStaticVoidMethod(c, m, a);
        }
      }
    }
  }

  int exitCode = 0;
  if (e->ExceptionCheck()) {
    exitCode = -1;
    e->ExceptionDescribe();
  }

  vm->DestroyJavaVM();

  return exitCode;
}
EOF

on Linux:

 $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
     -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o

on Mac OS X:

 $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin \
     -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o

on Windows:

 $ g++ -fno-exceptions -fno-rtti -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/win32" \
     -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o

5. Link the objects produced above to produce the final executable, and optionally strip its symbols.

on Linux:

$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello

on Mac OS X:

$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation
$ strip -S -x hello

on Windows:

$ dlltool -z hello.def *.o
$ dlltool -d hello.def -e hello.exp
$ gcc hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \
    -lIphlpapi -mwindows -mconsole -o hello.exe
$ strip --strip-all hello.exe

Embedding with ProGuard and a Boot Image

The following illustrates how to embed an application as above, except this time we preprocess the code using ProGuard and build a boot image from it for quicker startup. The pros and cons of using ProGuard are as follow:

  • Pros: ProGuard will eliminate unused code, optimize the rest, and obfuscate it as well for maximum space savings

  • Cons: increased build time, especially for large applications, and extra effort needed to configure it for applications which rely heavily on reflection and/or calls to Java from native code

For boot image builds:

  • Pros: the boot image build pre-parses all the classes and compiles all the methods, obviating the need for JIT compilation at runtime. This also makes garbage collection faster, since the pre-parsed classes are never visited.

  • Cons: the pre-parsed classes and AOT-compiled methods take up more space in the executable than the equivalent class files. In practice, this can make the executable 30-50% larger. Also, AOT compilation does not yet yield significantly faster or smaller code than JIT compilation. Finally, floating point code may be slower on 32-bit x86 since the compiler cannot assume SSE2 support will be available at runtime, and the x87 FPU is not supported except via out-of-line helper functions.

Note you can use ProGuard without using a boot image and vice-versa, as desired.

The following instructions assume we are building for Linux/x86_64. Please refer to the previous example for guidance on other platforms.

1. Build Avian, create a new directory, and populate it with the VM object files.

$ make bootimage=true
$ mkdir hello
$ cd hello
$ ar x ../build/linux-x86_64-bootimage/libavian.a

2. Create a stage1 directory and extract the contents of the class library jar into it.

$ mkdir stage1
$ (cd stage1 && jar xf ../../build/linux-x86_64-bootimage/classpath.jar)

3. Build the Java code and add it to stage1.

 $ cat >Hello.java <<EOF
public class Hello {
  public static void main(String[] args) {
    System.out.println("hello, world!");
  }
}
EOF
 $ javac -bootclasspath stage1 -d stage1 Hello.java

4. Create a ProGuard configuration file specifying Hello.main as the entry point.

 $ cat >hello.pro <<EOF
-keep class Hello {
   public static void main(java.lang.String[]);
 }
EOF

5. Run ProGuard with stage1 as input and stage2 as output.

 $ java -jar ../../proguard4.6/lib/proguard.jar \
     -dontusemixedcaseclassnames -injars stage1 -outjars stage2 \
     @../vm.pro @hello.pro

(note: The -dontusemixedcaseclassnames option is only needed when building on systems with case-insensitive filesystems such as Windows and OS X. Also, you'll need to add -ignorewarnings if you use the OpenJDK class library since the openjdk-src build does not include all the JARs from OpenJDK, and thus ProGuard will not be able to resolve all referenced classes. If you actually plan to use such classes at runtime, you'll need to add them to stage1 before running ProGuard. Finally, you'll need to add @../openjdk.pro to the above command when using the OpenJDK library.)

6. Build the boot and code images.

 $ ../build/linux-x86_64-bootimage/bootimage-generator \
    -cp stage2 \
    -bootimage bootimage-bin.o \
    -codeimage codeimage-bin.o \
    -hostvm ../build/linux-x86_64-interpret/libjvm.so

Note that you can override the default names for the start and end symbols in the boot/code image by also passing:

-bootimage-symbols my_bootimage_start:my_bootimage_end \
-codeimage-symbols my_codeimage_start:my_codeimage_end

7. Write a driver which starts the VM and runs the desired main method. Note the bootimageBin function, which will be called by the VM to get a handle to the embedded boot image. We tell the VM about this function via the "avian.bootimage" property.

Note also that this example includes no resources besides class files. If our application loaded resources such as images and properties files via the classloader, we would also need to embed the jar file containing them. See the previous example for instructions.

$ cat >bootimage-main.cpp <<EOF
#include "stdint.h"
#include "jni.h"

#if (defined __MINGW32__) || (defined _MSC_VER)
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT __attribute__ ((visibility("default")))
#endif

#if (! defined __x86_64__) && ((defined __MINGW32__) || (defined _MSC_VER))
#  define BOOTIMAGE_BIN(x) binary_bootimage_bin_##x
#  define CODEIMAGE_BIN(x) binary_codeimage_bin_##x
#else
#  define BOOTIMAGE_BIN(x) _binary_bootimage_bin_##x
#  define CODEIMAGE_BIN(x) _binary_codeimage_bin_##x
#endif

extern "C" {

  extern const uint8_t BOOTIMAGE_BIN(start)[];
  extern const uint8_t BOOTIMAGE_BIN(end)[];

  EXPORT const uint8_t*
  bootimageBin(size_t* size)
  {
    *size = BOOTIMAGE_BIN(end) - BOOTIMAGE_BIN(start);
    return BOOTIMAGE_BIN(start);
  }

  extern const uint8_t CODEIMAGE_BIN(start)[];
  extern const uint8_t CODEIMAGE_BIN(end)[];

  EXPORT const uint8_t*
  codeimageBin(size_t* size)
  {
    *size = CODEIMAGE_BIN(end) - CODEIMAGE_BIN(start);
    return CODEIMAGE_BIN(start);
  }

} // extern "C"

int
main(int ac, const char** av)
{
  JavaVMInitArgs vmArgs;
  vmArgs.version = JNI_VERSION_1_2;
  vmArgs.nOptions = 2;
  vmArgs.ignoreUnrecognized = JNI_TRUE;

  JavaVMOption options[vmArgs.nOptions];
  vmArgs.options = options;

  options[0].optionString
    = const_cast<char*>("-Davian.bootimage=bootimageBin");

  options[1].optionString
    = const_cast<char*>("-Davian.codeimage=codeimageBin");

  JavaVM* vm;
  void* env;
  JNI_CreateJavaVM(&vm, &env, &vmArgs);
  JNIEnv* e = static_cast<JNIEnv*>(env);

  jclass c = e->FindClass("Hello");
  if (not e->ExceptionCheck()) {
    jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V");
    if (not e->ExceptionCheck()) {
      jclass stringClass = e->FindClass("java/lang/String");
      if (not e->ExceptionCheck()) {
        jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0);
        if (not e->ExceptionCheck()) {
          for (int i = 1; i < ac; ++i) {
            e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i]));
          }

          e->CallStaticVoidMethod(c, m, a);
        }
      }
    }
  }

  int exitCode = 0;
  if (e->ExceptionCheck()) {
    exitCode = -1;
    e->ExceptionDescribe();
  }

  vm->DestroyJavaVM();

  return exitCode;
}
EOF

 $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \
     -D_JNI_IMPLEMENTATION_ -c bootimage-main.cpp -o main.o

8. Link the objects produced above to produce the final executable, and optionally strip its symbols.

$ g++ -rdynamic *.o -ldl -lpthread -lz -o hello
$ strip --strip-all hello

Trademarks

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

The Avian project is not affiliated with Oracle.

Comments
  • WinRT in AOT mode

    WinRT in AOT mode

    Do you have plans of supporting WinRT or WP8 in AOT mode?

    Currently I'm trying to do that on my own, but unfortunately I'm completely lost in makefile, since it seems that when bootimage=true, libavian for target platform still compiles code that supports JIT. Is there any option to split AOT and JIT mode during compilation: e.g. completely ifdef-out JIT code when AOT is requested, or something like that.

    opened by alexey-pelykh 86
  • Several methods missing in java.lang.Class

    Several methods missing in java.lang.Class

    We (me and @JustAMan) have tried using GSON (very popular Java JSON serializing/deserializing library) with Avian + Android classpath, and it turns out that Class misses several methods that are needed by GSON. Also note that Class.java is always taken from Avian classpath, so this issue is relevant for all Avian versions (i.e. both Avian's own classpath and Android classpath).

    Namely:

    Class.isAnonymousClass
    Class.isLocalClass
    Class.getGenericInterfaces
    

    are missing or throwing UnsupportedOperationException.

    We cannot progress further in finding what GSON needs except those three as we cannot stub getGenericInterfaces with something meaningful (stubbing it with empty list results in ArrayIndexOutOfBoundsException somewhere in the code path so GSON needs that method to provide correct results).

    It would be wonderful if you could share your thoughts on where we could get the data needed for those methods if you cannot provide a quick fix yourself.

    opened by bigfatbrowncat 66
  • Can't find class under Windows

    Can't find class under Windows

    I managed to build Avian with the Android classpath on Windows x86_64 (using mingw-w64), but now I have a strange problem.

    If I run such code:

    jclass c = e->FindClass("packagename/ClassName");
    if (e->ExceptionCheck())
    {
        exitCode = -1;
        e->ExceptionDescribe();
    }
    

    I get an error report:

    java/lang/NoClassDefFoundError: packagename/ClassName
    

    Everything's linked correctly with all jar files (I use static linkage everywhere and build a single executable embedding everything).

    This code works like a charm on OS X. And it worked well everywhere with Avian default classpath. I have no idea about how the changing of classpath libraries could influence VM core behavior.

    I used some small hacks and tricks to build Android classpath on Windows, for example I changed the definition for jchar from unsigned short to wchar_t (I hope they are the same on Windows) in order to avoid many conversion errors.

    I understand that there is too few information, but I just don't know where to find the bug. Debugging everything (including android classpath C++ sources) looks a bit scary.

    opened by bigfatbrowncat 31
  • Stand-alone Build does not seem to work

    Stand-alone Build does not seem to work

    Hello. I have trouble getting the non-dynamic build with the OpenJDK to work.

    $ ./avian -jar ~/jruby/jruby.jar
    java/lang/UnsatisfiedLinkError: library not found in /usr/lib/jvm/java-7-openjdk/jre/lib/amd64:/usr/lib/jvm/java-7-openjdk/jre/lib/amd64/xawt: libverify.so
    

    After looking at the directory in the above error message, I found libverify.so without a problem. I compiled Avian with make openjdk=/usr/lib/jvm/java-7-openjdk openjdk_source=/usr/lib/jvm/java-7-openjdk/src. This takes place in the build output directory ( aka build/linux-x86_64-openjdk ) I am running Arch Linux, x86_64.

    Greetings, vifino

    opened by vifino 25
  • VM deadlock on iOS

    VM deadlock on iOS

    Deadlock happens with following Hello.java only on arm-ios-avianclasslib and arm-ios-libcore64. There is no problem on arm-android, x64-osx and x86-linux.

    public class Hello {
      public Hello(long peer) throws Exception {
          final int[] counter = new int[2];
          new Thread() {
              @Override
              public void run() {
                  while (true) { // frequent monitorenter/exit
                      synchronized (this) {
                          counter[0]++;
                      }
                  }
              }
          }.start();
          new Thread() {
              @Override
              public void run() {
                  while (true) { // frequent class metadata search
                      try {
                          Class.forName("java.lang.Object");
                      } catch (ClassNotFoundException e) {
                          e.printStackTrace();
                      }
                      synchronized (this) {
                          counter[1]++;
                      }
                  }
              }
          }.start();
          new Thread() {
              @Override
              public void run() {
                  while (true) { // watchdog
                      System.err.println(counter[0] + " / " + counter[1]);
                      try {
                          Thread.sleep(1000);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  }
              }
          }.start();
      }
    
      public void draw(int x, int y, int width, int height) {
      }
    
      public void dispose() {
      }
    }
    
    opened by tarotanaka0 20
  • java.net.Socket implementation

    java.net.Socket implementation

    I created a basic clean-room implementation of java.net.Socket class (and improved some connected additional classes).

    The implementation doesn't contain all the methods of the original one, but it is sufficient to connect to a remote server and send/receive data.

    I tested it by connecting to an HTTP-server under Windows 7 and OS X 10.8. It works satisfactory.

    As for now only TCP-socket is implemented for IPv4 addresses.

    If you accept this pull-request I'll try to resolve all possible bugs connected to it. And in addition I'm going to implement ServerSocket soon.

    opened by bigfatbrowncat 20
  • git repo is way too big

    git repo is way too big

    The git repo now weighs in at over 100MB, even though the master working copy is only 4.9MB. That's ridiculous.

    I propose we do the following:

    • move obsolete branches to forks (e.g. move the invokeinterface branch to dicej/avian, since it will probably never be merged, but I want to preserve it for later reference)
    • remove gh-pages and figure out a different way to store the website outside the repo without breaking it like we did last time we tried
    • rewrite history to delete accidentally-checked in binaries, e.g. http://www.rallydev.com/community/engineering/shrinking-git-repository-move-githubcom
    opened by dicej 18
  • Error occured when compile avian using cygwin 1.7 on Win 7 sp1

    Error occured when compile avian using cygwin 1.7 on Win 7 sp1

    Edison@admin-PC /local/src/avian
    $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_45"
    
    Edison@admin-PC /local/src/avian
    $ make
    compiling build/windows-i386/tools/type-generator/main-build.o
    src/tools/type-generator/main.cpp:11:20: fatal error: stdlib.h: No such file or                  directory
    compilation terminated.
    makefile:1717: recipe for target `build/windows-i386/tools/type-generator/main-b                 uild.o' failed
    make: *** [build/windows-i386/tools/type-generator/main-build.o] Error 1
    
    Edison@admin-PC /local/src/avian
    $ apt-cyg show
    The following packages are installed:
    _autorebase
    _update-info-dir
    alternatives
    base-cygwin
    base-files
    bash
    bzip2
    coreutils
    cygutils
    cygwin
    dash
    diffutils
    dos2unix
    editrights
    file
    findutils
    gawk
    gcc-mingw-g++
    gettext
    grep
    groff
    gzip
    ipc-utils
    less
    libattr1
    libbz2_1
    libffi6
    libgcc1
    libgcrypt11
    libgmp10
    libgmp3
    libgnutls26
    libgpg-error0
    libiconv2
    libidn11
    libintl8
    liblzma5
    liblzo2_2
    libmpc3
    libmpfr4
    libncurses10
    libncursesw10
    libp11-kit0
    libpcre0
    libpopt0
    libreadline7
    libstdc++6
    libtasn1_3
    login
    make
    man
    mingw-binutils
    mingw-gcc-core
    mingw-gcc-g++
    mingw-pthreads
    mingw-runtime
    mingw-w32api
    mingw64-i686-binutils
    mingw64-i686-gcc-core
    mingw64-i686-gcc-g++
    mingw64-i686-runtime
    mingw64-i686-winpthreads
    mingw64-x86_64-binutils
    mingw64-x86_64-gcc-core
    mingw64-x86_64-gcc-g++
    mingw64-x86_64-runtime
    mingw64-x86_64-winpthreads
    mintty
    rebase
    run
    sed
    tar
    terminfo
    texinfo
    tzcode
    vim-minimal
    wget
    which
    xz
    zlib0
    
    opened by hydra1983 17
  • Begin using c++11 features

    Begin using c++11 features

    This is mostly to start a discussion; no need to merge this immediately.

    See here for reference on c++11 feature support in compilers: https://wiki.apache.org/stdcxx/C++0xCompilerSupport

    I'm using six features here:

    • nullptr constant - basically, just a 0 constant that's only valid for pointer types - since gcc 4.6 and MSVC 10
    • Range-based / enhanced for loops - since gcc 4.6 and MSVC 11
    • auto (deduced variable types) - since gcc 4.4 and MSVC 10
    • variadic templates - since gcc 4.4 and MSVC 11
    • enum classes - since gcc 4.4 and MSVC 11
    • constexpr - since gcc 4.6 with initial support in the latest CTP of MSVC 13 (2014)

    (All these are available in clang 3.1 and up)

    Depending on gcc 4.6 means on debian squeeze and wheezy, we'd have to use a the non-default, explicitly versioned 'gcc-4.6' package (which I believe adds -4.6 to the name, so we'd have to adjust the makefile).

    With respect to MSVC support, we can either:

    • Not use constexpr (i.e. not apply that commit)
    • Not support anything but that latest CTP (which may or may not work, since the support is apparently incomplete; I haven't tried it yet)
    • Use some preprocessor magic to get rid of the constexpr keyword on msvc and live with potentially sub-par performance.

    FWIW, I think the three most useful features here are the range-based for loops (which wouldn't be difficult to start using more places), auto type deduction, and variadic templates (particularly how I'm using them to get rid of the C-style variadic Compiler::call method.

    We can also pick gcc 4.4 as a target and still get some useful features.

    Is anyone using a current version of avian with MSVC? I tried a while back and gave up.

    Thoughts? Concerns?

    opened by joshuawarner32 16
  • busy wait can block entire VM

    busy wait can block entire VM

    In order for a thread to enter the "exclusive" state such that no other threads are active in the VM, it must wait for all active threads to enter the "idle" state. In order for this to happen in a timely manner, threads must check frequently to see if a thread is waiting to enter the exclusive state. These checks happen at every memory allocation, wait, sleep, native call, etc. However, if a thread is in a busy loop that does none of those things, it will block any other thread from entering that state and eventually cause all other threads to block.

    The proper way to address this is to detect such loops (or tail recursion in tail-call-optimized builds) at compile or interpret time and insert explicit checks.

    See also https://github.com/ReadyTalk/avian/commit/5d3dc707cb1af99cbe335674f148aedef0b09e8a

    bug 
    opened by dicej 14
  • Some fixes for the new Android classpath version + reflection improvements

    Some fixes for the new Android classpath version + reflection improvements

    This pull request contains some changes made by @dicej, @JustAMan and me in order to support the new Android classpath version + improvements for GSON

    This is connected with another pull request: https://github.com/dicej/android-libcore64/pull/11

    opened by bigfatbrowncat 13
  • Fails to compile on a modern Linux system, fixed via PR

    Fails to compile on a modern Linux system, fixed via PR

    Various identifiers from Avian's vm::OpCode enum - fadd, fmul, fsub, fdiv - clash with fadd, fmul, fsub, fdiv declared elsewhere when compiling on a modern Linux system. This results in gcc complaining about ambiguity (existentially understandable, but not helpful in this case).

    Minimum viable patch submitted via PR #568

    opened by paulie-g 0
  • Minimum viable fix for enums from vm namespaces clashing with identifiers from includes

    Minimum viable fix for enums from vm namespaces clashing with identifiers from includes

    Various identifiers from Avian's vm::OpCode enum - fadd, fmul, fsub, fdiv - clash with fadd, fmul, fsub, fdiv declared elsewhere when compiling on a modern Linux system. This patch is a kludge obviously, but given that this is not an actively maintained project, I chose to make it as small as possible so it doesn't clash with other patches in future.

    opened by paulie-g 0
  • File Descriptor Leak in NIO

    File Descriptor Leak in NIO

    Hi, I known this project is currently inactive, however I am placing this here so others can see.

    I have found a file descriptor leak in the NIO accept call. For now I have attached a patch, I am not sure this fix is the correct one, there where a number of options, but this was the least-changed one.

    fix-nio-fd-leak.patch.txt

    opened by mretallack 0
  • java/lang/annotation/AnnotationFormatError: Unexpected end of annotations.

    java/lang/annotation/AnnotationFormatError: Unexpected end of annotations.

    cygwin win10 openjdk-1.8.0.181-1.b13.ojdkbuild.windows.x86

    package extra; import javax.jws.WebResult; import javax.jws.WebService; import javax.xml.ws.Endpoint;

    @WebService public class HelloWS { public void HelloWord() { System.out.println("hello, world!"); } public static void main(String[] args) { String address = "http://127.0.0.1:8089/test"; Endpoint.publish(address + "/helloService", new HelloWS()); System.out.println("hello, world!"); } }

    $ ./build/windows-i386-openjdk-src/avian -cp build/windows-i386-openjdk-src/tes t extra/HelloWS java/lang/annotation/AnnotationFormatError: Unexpected end of annotations. at sun/reflect/annotation/AnnotationParser.parseAnnotations (line 74) at java/lang/Class.createAnnotationData (line 3521) at java/lang/Class.annotationData (line 3510) at java/lang/Class.getAnnotation (line 3415) at com/sun/xml/internal/bind/v2/model/annotation/RuntimeInlineAnnotationReader.getClassAnnotation (line 91) at com/sun/xml/internal/bind/v2/model/annotation/RuntimeInlineAnnotationReader.getClassAnnotation (line 42) at com/sun/xml/internal/bind/v2/model/impl/ModelBuilder.getTypeInfo (line 370) at com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl.getTypeInfoSet (line 439) at com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl. (line 277) at com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl. (line 124) at com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl$JAXBContextBuilder.build (line 1123) at com/sun/xml/internal/bind/v2/ContextFactory.createContext (line 147) at com/sun/xml/internal/bind/api/JAXBRIContext.newInstance (line 152) at com/sun/xml/internal/bind/api/JAXBRIContext.newInstance (line 96) at com/sun/xml/internal/ws/developer/JAXBContextFactory$1.createJAXBContext (line 98) at com/sun/xml/internal/ws/db/glassfish/JAXBRIContextFactory.newContext (line 79) at com/sun/xml/internal/ws/spi/db/BindingContextFactory.create (line 167) at com/sun/xml/internal/ws/model/AbstractSEIModelImpl$1.run (line 203) at com/sun/xml/internal/ws/model/AbstractSEIModelImpl$1.run (line 176) at java/security/AccessController.doPrivileged (native) at com/sun/xml/internal/ws/model/AbstractSEIModelImpl.createJAXBContext (line 176) at com/sun/xml/internal/ws/model/AbstractSEIModelImpl.postProcess (line 95) at com/sun/xml/internal/ws/model/RuntimeModeler.buildRuntimeModel (line 309) at com/sun/xml/internal/ws/db/DatabindingImpl. (line 85) at com/sun/xml/internal/ws/db/DatabindingProviderImpl.create (line 59) at com/sun/xml/internal/ws/db/DatabindingProviderImpl.create (line 43) at com/sun/xml/internal/ws/db/DatabindingFactoryImpl.createRuntime (line 105) at com/sun/xml/internal/ws/server/EndpointFactory.createSEIModel (line 453) at com/sun/xml/internal/ws/server/EndpointFactory.create (line 269) at com/sun/xml/internal/ws/server/EndpointFactory.createEndpoint (line 144) at com/sun/xml/internal/ws/api/server/WSEndpoint.create (line 563) at com/sun/xml/internal/ws/api/server/WSEndpoint.create (line 545) at com/sun/xml/internal/ws/transport/http/server/EndpointImpl.createEndpoint (line 308) at com/sun/xml/internal/ws/transport/http/server/EndpointImpl.publish (line 231) at com/sun/xml/internal/ws/spi/ProviderImpl.createAndPublishEndpoint (line 126) at javax/xml/ws/Endpoint.publish (line 240) at extra/HelloWS.main (line 13)

    opened by chinacharis 0
  • invokedynamic leads to accessing null dynamicTable in addDynamic.

    invokedynamic leads to accessing null dynamicTable in addDynamic.

    I'm hitting a null pointer crash in Avian, somewhere in the guts of handling an invokedynamic instruction. This is with avian in "compile mode". It doesn't matter if Avian is compiled with the JDK image/source or with Avian's classpath.

    This was compiled and run on x64 Ubuntu 16.04.5 LTS and another Linux-based ARM platform.

    The crash details from debugger:

    CLICK ME: Backtrace from lldb
    Process 14395 stopped
    * thread #3: tid = 14399, 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373, name = 'avian-dynamic', stop reason = signal SIGSEGV: invalid address (fault address: 0x8)
        frame #0: 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373
       1370	    compileRoots(t)->dynamicThunks()->body()[index * 2] = thunk;
       1371	    compileRoots(t)->dynamicThunks()->body()[(index * 2) + 1] = size;
       1372	
    -> 1373	    t->dynamicTable[index] = reinterpret_cast<void*>(thunk);
       1374	
       1375	    roots(t)->invocations()->setBodyElement(t, index, invocation);
       1376	  }
    (lldb) thread backtrace
    * thread #3: tid = 14399, 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373, name = 'avian-dynamic', stop reason = signal SIGSEGV: invalid address (fault address: 0x8)
      * frame #0: 0x00007ffff7af5564 libjvm.so`(anonymous namespace)::local::addDynamic(t=0x0000555555971c58, invocation=0x00007fffe401e758)::local::MyThread *, vm::GcInvocation *) + 1482 at compile.cpp:1373
        frame #1: 0x00007ffff7b0638f libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, initialFrame=0x00007ffff0de8ed0, initialIp=0, exceptionHandlerStart=-1)::local::MyThread *, (anonymous namespace)::local::Frame *, unsigned int, int) + 21271 at compile.cpp:5289
        frame #2: 0x00007ffff7b0e96e libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, context=0x00007ffff0de9040)::local::MyThread *, (anonymous namespace)::local::Context *) + 1242 at compile.cpp:7378
        frame #3: 0x00007ffff7b2375e libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, allocator=0x000055555575d290, bootContext=0x0000000000000000, method=0x00007fffe401f5a0)::local::MyThread *, avian::util::FixedAllocator *, (anonymous namespace)::local::BootContext *, vm::GcMethod *) + 488 at compile.cpp:10664
        frame #4: 0x00007ffff7b15bd5 libjvm.so`(anonymous namespace)::local::MyProcessor::invokeList(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007fffe401f5a0, this_=0x0000000000000000, indirectObjects=false, arguments=0x00007ffff0de9320) const + 757 at compile.cpp:9187
        frame #5: 0x00007ffff7ad110b libjvm.so`vm::Processor::invoke(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007fffe401f5a0, this_=0x0000000000000000) + 215 at processor.h:207
        frame #6: 0x00007ffff7ab54f8 libjvm.so`vm::initClass(t=0x0000555555971c58, c=0x00007fffe401f6a0) + 312 at machine.cpp:5267
        frame #7: 0x00007ffff7b2362b libjvm.so`(anonymous namespace)::local::compile(t=0x0000555555971c58, allocator=0x000055555575d290, bootContext=0x0000000000000000, method=0x00007fffe401f458)::local::MyThread *, avian::util::FixedAllocator *, (anonymous namespace)::local::BootContext *, vm::GcMethod *) + 181 at compile.cpp:10633
        frame #8: 0x00007ffff7b1780c libjvm.so`(anonymous namespace)::local::compileMethod2(t=0x0000555555971c58, ip=0x000000004005b08c)::local::MyThread *, void *) + 248 at compile.cpp:9645
        frame #9: 0x00007ffff7b0f02d libjvm.so`(anonymous namespace)::local::compileMethod(t=0x0000555555971c58)::local::MyThread *) + 110 at compile.cpp:7472
        frame #10: 0x000000004000001b
        frame #11: 0x00007ffff7b13337 libjvm.so`(anonymous namespace)::local::invoke(thread=0x0000555555971c58, method=0x00007ffff10def78, arguments=0x00007ffff0de9b70)::local::ArgumentList *) + 597 at compile.cpp:8555
        frame #12: 0x00007ffff7b15bf2 libjvm.so`(anonymous namespace)::local::MyProcessor::invokeList(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007ffff10def78, this_=0x0000555555897460, indirectObjects=false, arguments=0x00007ffff0de9c20) const + 786 at compile.cpp:9189
        frame #13: 0x00007ffff7ad110b libjvm.so`vm::Processor::invoke(this=0x000055555575d1e8, t=0x0000555555971c58, method=0x00007ffff10def78, this_=0x0000555555897460) + 215 at processor.h:207
        frame #14: 0x00007ffff7b2fda7 libjvm.so`(anonymous namespace)::local::MyClasspath::runThread(this=0x0000555555758538, t=0x0000555555971c58) const + 179 at classpath-openjdk.cpp:622
        frame #15: 0x00007ffff7ae0c50 libjvm.so`vm::runJavaThread(t=0x0000555555971c58) + 73 at machine.h:1806
        frame #16: 0x00007ffff7ae0cff libjvm.so`vm::runThread(t=0x0000555555971c58, (null)=0x0000000000000000) + 152 at machine.h:1820
        frame #17: 0x00007ffff7b7efe6 libjvm.so`vmRun + 47
        frame #18: 0x00007ffff7ae0b5a libjvm.so`vm::runRaw(t=0x0000555555971c58, function=(libjvm.so`vm::runThread(vm::Thread*, unsigned long*) at machine.h:1812), arguments=0x0000000000000000)(vm::Thread*, unsigned long*), unsigned long*) + 78 at machine.h:1793
        frame #19: 0x00007ffff7ae0bda libjvm.so`vm::run(t=0x0000555555971c58, function=(libjvm.so`vm::runThread(vm::Thread*, unsigned long*) at machine.h:1812), arguments=0x0000000000000000)(vm::Thread*, unsigned long*), unsigned long*) + 83 at machine.h:1801
        frame #20: 0x00007ffff7ae096c libjvm.so`vm::Thread::Runnable::run(this=0x0000555555971ce0) + 72 at machine.h:1769
        frame #21: 0x00007ffff7a94c01 libjvm.so`(anonymous namespace)::run(r=0x0000555555971ce0) + 50 at posix.cpp:101
        frame #22: 0x00007ffff6f846ba libpthread.so.0`start_thread + 202
        frame #23: 0x00007ffff77c441d libc.so.6`__clone + 109 at clone.S:109
    

    Probing some variables a bit further:

    CLICK ME: print of the Thread variable in debugger
    (lldb) frame variable *t
    error: libjvm.so 0x000002a5: DW_TAG_member '__size' refers to type 0x000002bc which extends beyond the bounds of 0x00000221
    error: libjvm.so 0x00000357: DW_TAG_member '__size' refers to type 0x00000375 which extends beyond the bounds of 0x000002d7
    ((anonymous namespace)::local::MyThread) *t = {
      vm::Thread = {
        vtable = 0x000055555575d9f8
        m = 0x000055555575d898
        parent = 0x00005555557628d8
        peer = 0x00005555558d0558
        child = 0x0000000000000000
        waitNext = 0x0000000000000000
        state = ActiveState
        criticalLevel = 0
        systemThread = 0x0000555555972630
        lock = 0x00005555559725d0
        javaThread = 0x0000555555897460
        exception = 0x0000000000000000
        heapIndex = 7303
        heapOffset = 8190
        protector = 0x00007ffff0de8ce0
        classInitStack = 0x00007ffff0de9480
        libraryLoadStack = 0x0000000000000000
        resource = 0x00007ffff0de8640
        checkpoint = 0x00007ffff0de99f0
        runnable = {
          t = 0x0000555555971c58
        }
        defaultHeap = 0x0000555555a91cd8
        heap = 0x00007fffe4011968
        backupHeap = {
          [0] = 0
          [1] = 0
          [2] = 0
          [3] = 0
          [4] = 0
          [5] = 0
          [6] = 0
          [7] = 0
          [8] = 0
          [9] = 0
          [10] = 0
          [11] = 0
          [12] = 0
          [13] = 0
          [14] = 0
          [15] = 0
          [16] = 0
          [17] = 0
          [18] = 0
          [19] = 0
          [20] = 0
          [21] = 0
          [22] = 0
          [23] = 0
          [24] = 0
          [25] = 0
          [26] = 0
          [27] = 0
          [28] = 0
          [29] = 0
          [30] = 0
          [31] = 0
          [32] = 0
          [33] = 0
          [34] = 0
          [35] = 0
          [36] = 0
          [37] = 0
          [38] = 0
          [39] = 0
          [40] = 0
          [41] = 0
          [42] = 0
          [43] = 0
          [44] = 0
          [45] = 0
          [46] = 0
          [47] = 0
          [48] = 0
          [49] = 0
          [50] = 0
          [51] = 0
          [52] = 0
          [53] = 0
          [54] = 0
          [55] = 0
          [56] = 0
          [57] = 0
          [58] = 0
          [59] = 0
          [60] = 0
          [61] = 0
          [62] = 0
          [63] = 0
          [64] = 0
          [65] = 0
          [66] = 0
          [67] = 0
          [68] = 0
          [69] = 0
          [70] = 0
          [71] = 0
          [72] = 0
          [73] = 0
          [74] = 0
          [75] = 0
          [76] = 0
          [77] = 0
          [78] = 0
          [79] = 0
          [80] = 0
          [81] = 0
          [82] = 0
          [83] = 0
          [84] = 0
          [85] = 0
          [86] = 0
          [87] = 0
          [88] = 0
          [89] = 0
          [90] = 0
          [91] = 0
          [92] = 0
          [93] = 0
          [94] = 0
          [95] = 0
          [96] = 0
          [97] = 0
          [98] = 0
          [99] = 0
          [100] = 0
          [101] = 0
          [102] = 0
          [103] = 0
          [104] = 0
          [105] = 0
          [106] = 0
          [107] = 0
          [108] = 0
          [109] = 0
          [110] = 0
          [111] = 0
          [112] = 0
          [113] = 0
          [114] = 0
          [115] = 0
          [116] = 0
          [117] = 0
          [118] = 0
          [119] = 0
          [120] = 0
          [121] = 0
          [122] = 0
          [123] = 0
          [124] = 0
          [125] = 0
          [126] = 0
          [127] = 0
          [128] = 0
          [129] = 0
          [130] = 0
          [131] = 0
          [132] = 0
          [133] = 0
          [134] = 0
          [135] = 0
          [136] = 0
          [137] = 0
          [138] = 0
          [139] = 0
          [140] = 0
          [141] = 0
          [142] = 0
          [143] = 0
          [144] = 0
          [145] = 0
          [146] = 0
          [147] = 0
          [148] = 0
          [149] = 0
          [150] = 0
          [151] = 0
          [152] = 0
          [153] = 0
          [154] = 0
          [155] = 0
          [156] = 0
          [157] = 0
          [158] = 0
          [159] = 0
          [160] = 0
          [161] = 0
          [162] = 0
          [163] = 0
          [164] = 0
          [165] = 0
          [166] = 0
          [167] = 0
          [168] = 0
          [169] = 0
          [170] = 0
          [171] = 0
          [172] = 0
          [173] = 0
          [174] = 0
          [175] = 0
          [176] = 0
          [177] = 0
          [178] = 0
          [179] = 0
          [180] = 0
          [181] = 0
          [182] = 0
          [183] = 0
          [184] = 0
          [185] = 0
          [186] = 0
          [187] = 0
          [188] = 0
          [189] = 0
          [190] = 0
          [191] = 0
          [192] = 0
          [193] = 0
          [194] = 0
          [195] = 0
          [196] = 0
          [197] = 0
          [198] = 0
          [199] = 0
          [200] = 0
          [201] = 0
          [202] = 0
          [203] = 0
          [204] = 0
          [205] = 0
          [206] = 0
          [207] = 0
          [208] = 0
          [209] = 0
          [210] = 0
          [211] = 0
          [212] = 0
          [213] = 0
          [214] = 0
          [215] = 0
          [216] = 0
          [217] = 0
          [218] = 0
          [219] = 0
          [220] = 0
          [221] = 0
          [222] = 0
          [223] = 0
          [224] = 0
          [225] = 0
          [226] = 0
          [227] = 0
          [228] = 0
          [229] = 0
          [230] = 0
          [231] = 0
          [232] = 0
          [233] = 0
          [234] = 0
          [235] = 0
          [236] = 0
          [237] = 0
          [238] = 0
          [239] = 0
          [240] = 0
          [241] = 0
          [242] = 0
          [243] = 0
          [244] = 0
          [245] = 0
          [246] = 0
          [247] = 0
          [248] = 0
          [249] = 0
          [250] = 0
          [251] = 0
          [252] = 0
          [253] = 0
          [254] = 0
          [255] = 0
        }
        backupHeapIndex = 0
        flags = 160
      }
      ip = 0x00000000400520c1
      stack = 0x00007ffff0de9818
      newStack = 0x00007ffff0de95d0
      scratch = 0x00007ffff0de9928
      continuation = 0x0000000000000000
      exceptionStackAdjustment = 0
      exceptionOffset = 0
      exceptionHandler = 0x0000000000000000
      tailAddress = 0x0000000000000000
      virtualCallTarget = 0x0000000000000000
      virtualCallIndex = 0
      heapImage = 0x0000000000000000
      codeImage = 0x0000000000000000
      thunkTable = 0x000055555575d3a8
      dynamicTable = 0x0000000000000000
      trace = 0x00007ffff0de9a20
      reference = 0x0000000000000000
      arch = 0x0000555555763250
      transition = 0x0000000000000000
      traceContext = 0x0000000000000000
      stackLimit = 140737234377120
      referenceFrame = 0x0000000000000000
      methodLockIsClean = true
    }
    (lldb) frame variable *t->m->processor->dynamicTable
    (void *) *t->m->processor->dynamicTable = 0x000000004005adf0
    

    .

    From that we can see that dynamicTable was set by the rest of the code in addDynamic for the t->m->processor, but this doesn't appear to have been copied over to the t->dynamicTable field? I think it might be a simple case of a missing call to updateDynamicTable(t, t); or something like that?? That might be understating the problem, however.

    Example application that results in this crash: https://github.com/Poddster/avian_null_dynamicTable

    That app is the smallest I can make it, though smaller examples might exist. Changing practically anything in this example app makes the problem disappear. (Infact using that information I've managed to make my original app not crash by working around the issue and accessing a class earlier than it normally would. This seems to "fix" the problem for me, though the underlying issue is obviously still present.)

    opened by Poddster 0
Eclipse Foundation 3k Dec 31, 2022
Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput.

Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput. Builds on Eclipse OMR (https://github.com/eclipse/omr) and combines with the Extensions for OpenJDK for OpenJ9 repo.

null 3k Jan 3, 2023
jextract is a tool which mechanically generates Java bindings from a native library headers.

Jextract jextract is a tool which mechanically generates Java bindings from a native library headers. This tools leverages the clang C API in order to

OpenJDK 120 Dec 30, 2022
A Java Virtual Machine - running on a Java Virtual Machine - running on a (jk).

Javaception A Java Virtual Machine - running on a Java Virtual Machine - running on a (jk). Goals JVMS compliant Java Virtual Machine Somewhat fast Re

null 33 Oct 10, 2022
Microhttp - a fast, scalable, event-driven, self-contained Java web server

Microhttp is a fast, scalable, event-driven, self-contained Java web server that is small enough for a programmer to understand and reason about.

Elliot Barlas 450 Dec 23, 2022
Chamomile is a Java Virtual Machine class file assembler and disassembler.

Chamomile is a Java Virtual Machine class file assembler and disassembler. Installation Maven <repositories> <repository> <id>jitpack.io</

null 15 May 24, 2022
Rework of html-java-dsl to work with newer Javas

java-html-dsl Example DSL for writing html in Java. Rework of benjiman/java-html-dsl to work with newer versions of Java This String doc = html(

Benji Weber 19 Jan 25, 2022
To quickly integrate your applications into the EdgeGallery platform, we provide the toolchain project to help developers quickly modify code and migrate applications to the platform.

Toolchain 工具链 工具链是MEC Developer开发者平台中的一个重要特性,当x86平台的App想要上车ARM平台时,底层的代码不可避免的需要进行修改或重写。 App提供者可以通过MEC Developer开发者平台中集成的工具链进行源代码分析,定位需要修改的源代码并根据指导意见进行修

EdgeGallery 19 Jan 7, 2022
Datumbox is an open-source Machine Learning framework written in Java which allows the rapid development of Machine Learning and Statistical applications.

Datumbox Machine Learning Framework The Datumbox Machine Learning Framework is an open-source framework written in Java which allows the rapid develop

Vasilis Vryniotis 1.1k Dec 9, 2022
Library for converting from one Java class to a dissimilar Java class with similar names based on the Bean convention

Beanmapper Beanmapper is a Java library for mapping dissimilar Java classes with similar names. The use cases for Beanmapper are the following: mappin

null 26 Nov 15, 2022
BlackBox is a virtual engine, it can clone and run virtual application on Android

BlackBox is a virtual engine, it can clone and run virtual application on Android, users don't have to install APK file to run the application on devices. BlackBox control all virtual applications, so you can do anything you want by using BlackBox.

null 1.6k Jan 3, 2023
A toy compiler that translates SysY (a subset of C language) into ARMv7a, implemented in Java15.

北京航空航天大学 No Segmentation Fault Work 队作品。 ayame A toy compiler that translates SysY (a subset of C language) into ARMv7a. Build javac -encoding UTF-8 $

null 57 Jan 2, 2023
ESA Cabin is a lightweight class isolation container for Java applications.

Cabin Cabin是一款Java类隔离框架,用于隔离各个模块之间、模块和业务之间使用的第三方依赖库。使用Cabin后,模块SDK将只是用自己指定 版本的三方依赖,不会被业务引入的依赖所影响,保证业务正常运行,提高业务的开发效率,减少中间件同学此类重复的支持工作。 概述 ESA Cabin用于解决

ESA Stack 22 Dec 1, 2022
JVM Explorer is a Java desktop application for browsing loaded class files inside locally running Java Virtual Machines.

JVM Explorer JVM Explorer is a Java desktop application for browsing loaded class files inside locally running Java Virtual Machines. Features Browse

null 109 Nov 30, 2022
jdbi is designed to provide convenient tabular data access in Java; including templated SQL, parameterized and strongly typed queries, and Streams integration

The Jdbi library provides convenient, idiomatic access to relational databases in Java. Jdbi is built on top of JDBC. If your database has a JDBC driv

null 1.7k Dec 27, 2022