From 887a32bc108bf6c9f8af7bf0d7b5f468ebf41ad7 Mon Sep 17 00:00:00 2001 From: Carsten Elton Sorensen Date: Fri, 21 Dec 2012 14:18:41 +0100 Subject: [PATCH 01/37] Added some members that should not be removed or renamed --- openjdk.pro | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/openjdk.pro b/openjdk.pro index d0b8de812f..3ffce4f58f 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -246,3 +246,39 @@ } -keep class sun.net.www.protocol.jar.Handler + +# These concurrent classes refer to certain members reflectively in their static initializers +-keepclassmembers class java.util.concurrent.ConcurrentHashMap$HashEntry { + *** next; +} + +-keepclassmembers class java.util.concurrent.CopyOnWriteArrayList { + *** lock; +} + +-keepclassmembers class java.util.concurrent.CountDownLatch { + *** allocationSpinLock; +} + +-keepclassmembers class java.util.concurrent.PriorityBlockingQueue { + *** allocationSpinLock; +} + +-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack { + *** head; +} + +-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue { + *** head; + *** tail; +} + +-keepclassmembers class java.util.concurrent.ConcurrentLinkedQueue$Node { + *** item; + *** next; +} + +-keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack$SNode { + *** match; + *** next; +} \ No newline at end of file From cad4719f7dcf2d239b3b39afd3cc7943503dbd4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Elton=20S=C3=B8rensen?= Date: Fri, 21 Dec 2012 09:56:21 +0100 Subject: [PATCH 02/37] Handle null pointer in PopLocalFrame --- src/jnienv.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/jnienv.cpp b/src/jnienv.cpp index f8a0ff3987..2a70b10855 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -3370,12 +3370,21 @@ PushLocalFrame(Thread* t, jint capacity) uint64_t popLocalFrame(Thread* t, uintptr_t* arguments) { - object result = *reinterpret_cast(arguments[0]); - PROTECT(t, result); + uint64_t r; + jobject presult = reinterpret_cast(arguments[0]); + if(presult != NULL) { + object result = *presult; + PROTECT(t, result); - t->m->processor->popLocalFrame(t); - - return reinterpret_cast(makeLocalReference(t, result)); + t->m->processor->popLocalFrame(t); + + r = reinterpret_cast(makeLocalReference(t, result)); + } else { + t->m->processor->popLocalFrame(t); + r = 0; + } + + return r; } jobject JNICALL From 5061d7fe4df365e8ca4f00511e782a4c08d7ed2d Mon Sep 17 00:00:00 2001 From: Mike Keesey Date: Tue, 25 Dec 2012 18:12:03 -0700 Subject: [PATCH 03/37] Making Thread's isInterrupted() non-static and make it use the current instance's interrupted variable. --- classpath/java/lang/Thread.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classpath/java/lang/Thread.java b/classpath/java/lang/Thread.java index 936351c809..3abfd3238e 100644 --- a/classpath/java/lang/Thread.java +++ b/classpath/java/lang/Thread.java @@ -151,8 +151,8 @@ public class Thread implements Runnable { private static native boolean interrupted(long peer); - public static boolean isInterrupted() { - return currentThread().interrupted; + public boolean isInterrupted() { + return interrupted; } public static void sleep(long milliseconds) throws InterruptedException { From a0cd542fcfddd5f8a5da3637ce3df84c4bfa767c Mon Sep 17 00:00:00 2001 From: Seth Goings Date: Wed, 26 Dec 2012 15:30:45 -0700 Subject: [PATCH 04/37] Update readme.txt --- readme.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index e9185b2c85..213c138485 100644 --- a/readme.txt +++ b/readme.txt @@ -12,13 +12,13 @@ on Mac OS X: $ build/darwin-i386/avian -cp build/darwin-i386/test Hello on Windows (MSYS): - $ git clone git://oss.readytalk.com/win32.git ../win32 + $ git clone git@github.com:ReadyTalk/win32.git ../win32 $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" $ make $ build/windows-i386/avian -cp build/windows-i386/test Hello on Windows (Cygwin): - $ git clone git://oss.readytalk.com/win32.git ../win32 + $ git clone git@github.com:ReadyTalk/win32.git ../win32 $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" $ make $ build/windows-i386/avian -cp build/windows-i386/test Hello @@ -191,13 +191,13 @@ Installing Cygwin: You may also find our win32 repository useful: (run this from the directory containing the avian directory) - $ git clone git://oss.readytalk.com/win32.git + $ git clone git@github.com: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 git://oss.readytalk.com/win64.git + $ git clone git@github.com:ReadyTalk/win64.git Building with the Microsoft Visual C++ Compiler From dd685de6e61fc4eb0044eb8f32169cdad9cb3518 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 31 Dec 2012 11:07:26 -0700 Subject: [PATCH 05/37] add extra empty line before heading in readme.txt This makes it consistent with the other headings. --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index 213c138485..eb1916f2a5 100644 --- a/readme.txt +++ b/readme.txt @@ -56,6 +56,7 @@ Avian can currently target the following platforms: Mac OS X (i386, x86_64 and 32-bit PowerPC) Apple iOS (i386 and ARM) + Building -------- From e8f560895b155a85099879c9c2eac7009a0624d4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 31 Dec 2012 11:56:35 -0700 Subject: [PATCH 06/37] preserve sun.misc.Launcher.getLauncher in openjdk.pro The VM calls this method when booting, so we need to tell ProGuard to retain it. --- openjdk.pro | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openjdk.pro b/openjdk.pro index 3ffce4f58f..69b4646090 100644 --- a/openjdk.pro +++ b/openjdk.pro @@ -14,6 +14,10 @@ public static void setProperties(java.util.Properties); } +-keep class sun.misc.Launcher { + public static sun.misc.Launcher getLauncher(); + } + -keep class java.lang.ClassLoader { private static java.lang.ClassLoader scl; private static boolean sclSet; @@ -281,4 +285,4 @@ -keepclassmembers class java.util.concurrent.SynchronousQueue$TransferStack$SNode { *** match; *** next; -} \ No newline at end of file +} From ccbe01c16a7f9e92c06b8b45299c69a387625f67 Mon Sep 17 00:00:00 2001 From: terekcampbell Date: Fri, 4 Jan 2013 14:03:15 -0700 Subject: [PATCH 07/37] Edit the top --- readme.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/readme.txt b/readme.txt index eb1916f2a5..1087777f81 100644 --- a/readme.txt +++ b/readme.txt @@ -1,3 +1,8 @@ +Avian - a lightweight Java virtual machine (JVM) +================================================ + +// Put travis thing here + Quick Start ----------- From dfbc34c3a4c8fcd6322ccf2a933afacd2627f0c0 Mon Sep 17 00:00:00 2001 From: terekcampbell Date: Fri, 4 Jan 2013 16:09:54 -0700 Subject: [PATCH 08/37] Will now look pretty when converted to .md --- readme.txt | 811 ++++++++++++++++++++++++++--------------------------- 1 file changed, 404 insertions(+), 407 deletions(-) diff --git a/readme.txt b/readme.txt index 1087777f81..0ebfc4540b 100644 --- a/readme.txt +++ b/readme.txt @@ -1,32 +1,30 @@ -Avian - a lightweight Java virtual machine (JVM) +Avian - A lightweight Java Virtual Machine (JVM) ================================================ -// Put travis thing here - Quick Start ----------- -on Linux: - $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed - $ make - $ build/linux-i386/avian -cp build/linux-i386/test Hello +#### on Linux: + $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed + $ make + $ build/linux-i386/avian -cp build/linux-i386/test Hello -on Mac OS X: - $ export JAVA_HOME=/Library/Java/Home - $ make - $ build/darwin-i386/avian -cp build/darwin-i386/test Hello +#### on Mac OS X: + $ export JAVA_HOME=/Library/Java/Home + $ make + $ build/darwin-i386/avian -cp build/darwin-i386/test Hello -on Windows (MSYS): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello +#### on Windows (MSYS): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello -on Windows (Cygwin): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello +#### on Windows (Cygwin): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello Adjust JAVA_HOME according to your system, but be sure to use forward slashes in the path. @@ -38,14 +36,10 @@ 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. More information is available at the -project web site: - - http://oss.readytalk.com/avian +project [web site](http://oss.readytalk.com/avian). If you have any trouble building, running, or embedding Avian, please -post a message to our discussion group: - - http://groups.google.com/group/avian +post a message to our [discussion group](http://groups.google.com/group/avian). That's also the place for any other questions, comments, or suggestions you might have. @@ -56,10 +50,10 @@ Supported Platforms Avian can currently target the following platforms: - Linux (i386, x86_64, ARM, and 32-bit PowerPC) - Windows (i386 and x86_64) - Mac OS X (i386, x86_64 and 32-bit PowerPC) - Apple iOS (i386 and ARM) + * Linux (i386, x86_64, ARM, and 32-bit PowerPC) + * Windows (i386 and x86_64) + * Mac OS X (i386, x86_64 and 32-bit PowerPC) + * Apple iOS (i386 and ARM) Building @@ -80,130 +74,129 @@ 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,darwin} \ - arch={i386,x86_64,powerpc,arm} \ - process={compile,interpret} \ - mode={debug,debug-fast,fast,small} \ - lzma= \ - ios={true,false} \ - bootimage={true,false} \ - heapdump={true,false} \ - tails={true,false} \ - continuations={true,false} \ - use-clang={true,false} \ - openjdk= \ - openjdk-src= + $ make \ + platform={linux,windows,darwin} \ + arch={i386,x86_64,powerpc,arm} \ + process={compile,interpret} \ + mode={debug,debug-fast,fast,small} \ + lzma= \ + ios={true,false} \ + bootimage={true,false} \ + heapdump={true,false} \ + tails={true,false} \ + continuations={true,false} \ + use-clang={true,false} \ + openjdk= \ + openjdk-src= - * platform - the target platform - default: output of $(uname -s | tr [:upper:] [:lower:]), - normalized in some cases (e.g. CYGWIN_NT-5.1 -> windows) + * `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) + * `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 + * `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 + * `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 at - http://www.7-zip.org/sdk.html). Currently, only version 9.20 of - the SDK has been tested, but other versions might work. - default: not set + * `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](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of +the SDK has been tested, but other versions might work. + * _default:_ not set - * ios - if true, cross-compile for iOS on OS X. Note that - non-jailbroken iOS devices do not allow JIT compilation, so only - process=interpret or bootimage=true builds will run on such - devices. See https://github.com/ReadyTalk/hello-ios for an - example of an Xcode project for iOS which uses Avian. - default: false + * `ios` - if true, cross-compile for iOS on OS X. Note that +non-jailbroken iOS devices do not allow JIT compilation, so only +process=interpret or bootimage=true builds will run on such +devices. See [here](https://github.com/ReadyTalk/hello-ios) for an +example of an Xcode project for iOS which uses Avian. + * _default:_ false - * 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 + * `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 - * heapdump - if true, implement avian.Machine.dumpHeap(String), - which, when called, will generate a snapshot of the heap in a - simple, ad-hoc format for memory profiling purposes. See - heapdump.cpp for details. - default: false + * `heapdump` - if true, implement avian.Machine.dumpHeap(String), +which, when called, will generate a snapshot of the heap in a +simple, ad-hoc format for memory profiling purposes. See +heapdump.cpp for details. + * _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 + * `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 + * `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 + * `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 OpenJDK class library instead of the default - Avian class library. See "Building with the OpenJDK Class - Library" below for details. - default: not set + * `openjdk` - if set, use 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 + * `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 These flags determine the name of the directory used for the build. -The name always starts with ${platform}-${arch}, and each non-default +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/i386 would be built in -build/linux-i386-debug-bootimage. This allows you to build with +_build/linux-i386-debug-bootimage_. This allows you to build with several different sets of options independently and even simultaneously without doing a clean build each time. If you are compiling for Windows, you may either cross-compile using MinGW or build natively on Windows under MSYS or Cygwin. -Installing MSYS: +#### Installing MSYS: - 1. Download and install the current MinGW and MSYS packages from + __1.__ Download and install the current MinGW and MSYS packages from mingw.org, selecting the C and C++ compilers when prompted. Use the post-install script to create the filesystem link to the compiler. - 2. Download GNU Make 3.81 from the MSYS download page + __2.__ Download GNU Make 3.81 from the MSYS download page (make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into - e.g. c:/msys/1.0. + _e.g. c:/msys/1.0_. -Installing Cygwin: +#### Installing Cygwin: - 1. Download and run setup.exe from cygwin.com, installing the base + __1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), 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 git@github.com:ReadyTalk/win32.git + $ git clone git@github.com: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 git@github.com:ReadyTalk/win64.git + $ git clone git@github.com:ReadyTalk/win64.git Building with the Microsoft Visual C++ Compiler @@ -221,23 +214,18 @@ versions 8, 9, and 10. Other versions may also work. 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 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.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 9.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 9.0\VC\LIB;" - - $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" - - $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" - - $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v6.0A\include;" + $ export PATH="/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.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 9.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 9.0\VC\LIB;" + $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" + $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" + $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.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 9.0/VC" - + $ make msvc="/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC" Building with the OpenJDK Class Library --------------------------------------- @@ -249,23 +237,23 @@ 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 + $ 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. To run an +from _/usr/lib/jvm/java-7-openjdk/jre_ at runtime. To run an application in this configuration, you'll need to make sure the VM is in your library search path. For example: - $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ - build/linux-x86_64-openjdk/avian-dynamic -cp /path/to/my/application \ - com.example.MyApplication + $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ + 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 + $ 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 @@ -278,61 +266,65 @@ 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 + $ 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 + $ 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 -git://oss.readytalk.com/avian-swt-examples.git for an example of using +_git://oss.readytalk.com/avian-swt-examples.git_ 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 +#### Debian-based Linux: +_Conventional build:_ - # stand-alone build: - apt-get install openjdk-7-jdk - apt-get source openjdk-7-jdk - apt-get build-dep openjdk-7-jdk + $ 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 + $ 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 - # https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port +####Mac OS X: +_Prerequisite:_ Build OpenJDK 7 according to [this site](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port). - # conventional build: - make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test +_Conventional build:_ - # stand-alone build: - make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ - openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image test - Windows (Cygwin): - # Prerequisite: build OpenJDK 7 according to - # http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction +_Stand-alone build:_ - # conventional build: - make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image test + $ make openjdk=$(pwd)/../jdk7u-dev/build/macosx-amd64/j2sdk-image \ + openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test - # stand-alone build: - make openjdk=$(pwd)/../jdk7u-dev/build/windows-i586/j2sdk-image \ - openjdk-src=$(pwd)/../p/jdk7u-dev/jdk/src test +####Windows (Cygwin): +_Prerequisite:_ Build OpenJDK 7 according to [this site](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). + +_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. @@ -344,7 +336,7 @@ Installing Installing Avian is as simple as copying the executable to the desired directory: - $ cp build/${platform}-${arch}/avian ~/bin/ + $ cp build/${platform}-${arch}/avian ~/bin/ Embedding @@ -357,158 +349,163 @@ 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). -Step 1: Build Avian, create a new directory, and populate it with the +__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 + $ make + $ mkdir hello + $ cd hello + $ ar x ../build/${platform}-${arch}/libavian.a + $ cp ../build/${platform}-${arch}/classpath.jar boot.jar -Step 2: Build the Java code and add it to the jar. +__2.__ Build the Java code and add it to the jar. - $ cat >Hello.java <Hello.java <embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(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"); + $ cat >embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); if (not e->ExceptionCheck()) { - jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); if (not e->ExceptionCheck()) { - for (int i = 1; i < ac; ++i) { - e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + 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); + } } - - e->CallStaticVoidMethod(c, m, a); } } + + int exitCode = 0; + if (e->ExceptionCheck()) { + exitCode = -1; + e->ExceptionDescribe(); + } + + vm->DestroyJavaVM(); + + return exitCode; } - } + EOF - int exitCode = 0; - if (e->ExceptionCheck()) { - exitCode = -1; - e->ExceptionDescribe(); - } +__on Linux:__ - vm->DestroyJavaVM(); + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o - return exitCode; -} -EOF +__on Mac OS X:__ -on Linux: - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/linux \ - -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + $ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ + -o main.o -on Mac OS X: - $ g++ -I$JAVA_HOME/include -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ - -o main.o +__on Windows:__ -on Windows: - $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \ - -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o + $ g++ -I$JAVA_HOME/include -I$JAVA_HOME/include/win32 \ + -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp -o main.o -Step 5: Link the objects produced above to produce the final +__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 Linux:__ -on Mac OS X: - $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello -framework CoreFoundation - $ strip -S -x hello + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello -on Windows: - $ dlltool -z hello.def *.o - $ dlltool -d hello.def -e hello.exp - $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ - -mwindows -mconsole -o hello.exe - $ strip --strip-all hello.exe +__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 + $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ + -mwindows -mconsole -o hello.exe + $ strip --strip-all hello.exe Embedding with ProGuard and a Boot Image ---------------------------------------- @@ -547,45 +544,45 @@ as desired. The following instructions assume we are building for Linux/i386. Please refer to the previous example for guidance on other platforms. -Step 1: Build Avian, create a new directory, and populate it with the +__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-i386-bootimage/libavian.a + $ make bootimage=true + $ mkdir hello + $ cd hello + $ ar x ../build/linux-i386-bootimage/libavian.a -Step 2: Create a stage1 directory and extract the contents of the +__2.__ Create a stage1 directory and extract the contents of the class library jar into it. - $ mkdir stage1 - $ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar) + $ mkdir stage1 + $ (cd stage1 && jar xf ../../build/linux-i386-bootimage/classpath.jar) -Step 3: Build the Java code and add it to stage1. +__3.__ Build the Java code and add it to stage1. - $ cat >Hello.java <Hello.java <hello.pro <hello.pro <bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); - - options[1].optionString - = const_cast("-Davian.codeimage=codeimageBin"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(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"); + $ cat >bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); + + options[1].optionString + = const_cast("-Davian.codeimage=codeimageBin"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(env); + + jclass c = e->FindClass("Hello"); if (not e->ExceptionCheck()) { - jobjectArray a = e->NewObjectArray(ac-1, stringClass, 0); + jmethodID m = e->GetStaticMethodID(c, "main", "([Ljava/lang/String;)V"); if (not e->ExceptionCheck()) { - for (int i = 1; i < ac; ++i) { - e->SetObjectArrayElement(a, i-1, e->NewStringUTF(av[i])); + 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); + } } - - 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 - int exitCode = 0; - if (e->ExceptionCheck()) { - exitCode = -1; - e->ExceptionDescribe(); - } +__8.__ Link the objects produced above to produce the final + executable, and optionally strip its symbols. - 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 - -Step 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 + $ g++ -rdynamic *.o -ldl -lpthread -lz -o hello + $ strip --strip-all hello Trademarks From cca7ade32e59eb9be08a23ec126017f04a18626c Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Fri, 4 Jan 2013 16:42:11 -0700 Subject: [PATCH 09/37] Changed the readme file to a Markdown file --- README.md | 732 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 732 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..8d27542f88 --- /dev/null +++ b/README.md @@ -0,0 +1,732 @@ +Avian - A lightweight Java Virtual Machine (JVM) +================================================ + +[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) + +Quick Start +----------- + +#### on Linux: + $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed + $ make + $ build/linux-i386/avian -cp build/linux-i386/test Hello + +#### on Mac OS X: + $ export JAVA_HOME=/Library/Java/Home + $ make + $ build/darwin-i386/avian -cp build/darwin-i386/test Hello + +#### on Windows (MSYS): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello + +#### on Windows (Cygwin): + $ git clone git@github.com:ReadyTalk/win32.git ../win32 + $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" + $ make + $ build/windows-i386/avian -cp build/windows-i386/test Hello + +Adjust JAVA_HOME according to your system, but be sure to use forward +slashes in the path. + + +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. More information is available at the +project [web site](http://oss.readytalk.com/avian). + +If you have any trouble building, running, or embedding Avian, please +post a message to our [discussion group](http://groups.google.com/group/avian). + +That's also the place for any other questions, comments, or +suggestions you might have. + + +Supported Platforms +------------------- + +Avian can currently target the following platforms: + + * Linux (i386, x86_64, ARM, and 32-bit PowerPC) + * Windows (i386 and x86_64) + * Mac OS X (i386, x86_64 and 32-bit PowerPC) + * Apple iOS (i386 and ARM) + + +Building +-------- + +Build requirements include: + + * GNU make 3.80 or later + * GCC 3.4 or later (4.5.1 or later for Windows/x86_64) + or LLVM Clang 3.1 or later (see use-clang option below) + * JDK 1.5 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,darwin} \ + arch={i386,x86_64,powerpc,arm} \ + process={compile,interpret} \ + mode={debug,debug-fast,fast,small} \ + lzma= \ + ios={true,false} \ + bootimage={true,false} \ + heapdump={true,false} \ + tails={true,false} \ + continuations={true,false} \ + use-clang={true,false} \ + openjdk= \ + openjdk-src= + + * `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](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of +the SDK has been tested, but other versions might work. + * _default:_ not set + + * `ios` - if true, cross-compile for iOS on OS X. Note that +non-jailbroken iOS devices do not allow JIT compilation, so only +process=interpret or bootimage=true builds will run on such +devices. See [here](https://github.com/ReadyTalk/hello-ios) for an +example of an Xcode project for iOS which uses Avian. + * _default:_ false + + * `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 + + * `heapdump` - if true, implement avian.Machine.dumpHeap(String), +which, when called, will generate a snapshot of the heap in a +simple, ad-hoc format for memory profiling purposes. See +heapdump.cpp for details. + * _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 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 + +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/i386 would be built in +_build/linux-i386-debug-bootimage_. This allows you to build with +several different sets of options independently and even +simultaneously without doing a clean build each time. + +If you are compiling for Windows, you may either cross-compile using +MinGW or build natively on Windows under MSYS or Cygwin. + +#### Installing MSYS: + + __1.__ Download and install the current MinGW and MSYS packages from + mingw.org, selecting the C and C++ compilers when prompted. Use the + post-install script to create the filesystem link to the compiler. + + __2.__ Download GNU Make 3.81 from the MSYS download page + (make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into + _e.g. c:/msys/1.0_. + +#### Installing Cygwin: + + __1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), 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 git@github.com: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 git@github.com: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. + +The MSVC build has been tested with Visual Studio Express Edition +versions 8, 9, and 10. Other versions may also work. + +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 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.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 9.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 9.0\VC\LIB;" + $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" + $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" + $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.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 9.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. To run an +application in this configuration, you'll need to make sure the VM is +in your library search path. For example: + + $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ + 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 +_git://oss.readytalk.com/avian-swt-examples.git_ 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](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port). + +_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](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). + +_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. + + +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 <embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(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 -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ + -o main.o + +__on Windows:__ + + $ g++ -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 + $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ + -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/i386. +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-i386-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-i386-bootimage/classpath.jar) + +__3.__ Build the Java code and add it to stage1. + + $ cat >Hello.java <hello.pro <bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); + + options[1].optionString + = const_cast("-Davian.codeimage=codeimageBin"); + + JavaVM* vm; + void* env; + JNI_CreateJavaVM(&vm, &env, &vmArgs); + JNIEnv* e = static_cast(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. \ No newline at end of file From 7caa479084bbcad5a1d3315dc74296f50f5e0935 Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Fri, 4 Jan 2013 16:45:47 -0700 Subject: [PATCH 10/37] Deleted the old readme.txt file --- readme.txt | 730 ----------------------------------------------------- 1 file changed, 730 deletions(-) delete mode 100644 readme.txt diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 0ebfc4540b..0000000000 --- a/readme.txt +++ /dev/null @@ -1,730 +0,0 @@ -Avian - A lightweight Java Virtual Machine (JVM) -================================================ - -Quick Start ------------ - -#### on Linux: - $ export JAVA_HOME=/usr/local/java # or wherever you have the JDK installed - $ make - $ build/linux-i386/avian -cp build/linux-i386/test Hello - -#### on Mac OS X: - $ export JAVA_HOME=/Library/Java/Home - $ make - $ build/darwin-i386/avian -cp build/darwin-i386/test Hello - -#### on Windows (MSYS): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="C:/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello - -#### on Windows (Cygwin): - $ git clone git@github.com:ReadyTalk/win32.git ../win32 - $ export JAVA_HOME="/cygdrive/c/Program Files/Java/jdk1.6.0_07" - $ make - $ build/windows-i386/avian -cp build/windows-i386/test Hello - -Adjust JAVA_HOME according to your system, but be sure to use forward -slashes in the path. - - -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. More information is available at the -project [web site](http://oss.readytalk.com/avian). - -If you have any trouble building, running, or embedding Avian, please -post a message to our [discussion group](http://groups.google.com/group/avian). - -That's also the place for any other questions, comments, or -suggestions you might have. - - -Supported Platforms -------------------- - -Avian can currently target the following platforms: - - * Linux (i386, x86_64, ARM, and 32-bit PowerPC) - * Windows (i386 and x86_64) - * Mac OS X (i386, x86_64 and 32-bit PowerPC) - * Apple iOS (i386 and ARM) - - -Building --------- - -Build requirements include: - - * GNU make 3.80 or later - * GCC 3.4 or later (4.5.1 or later for Windows/x86_64) - or LLVM Clang 3.1 or later (see use-clang option below) - * JDK 1.5 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,darwin} \ - arch={i386,x86_64,powerpc,arm} \ - process={compile,interpret} \ - mode={debug,debug-fast,fast,small} \ - lzma= \ - ios={true,false} \ - bootimage={true,false} \ - heapdump={true,false} \ - tails={true,false} \ - continuations={true,false} \ - use-clang={true,false} \ - openjdk= \ - openjdk-src= - - * `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](http://www.7-zip.org/sdk.html)). Currently, only version 9.20 of -the SDK has been tested, but other versions might work. - * _default:_ not set - - * `ios` - if true, cross-compile for iOS on OS X. Note that -non-jailbroken iOS devices do not allow JIT compilation, so only -process=interpret or bootimage=true builds will run on such -devices. See [here](https://github.com/ReadyTalk/hello-ios) for an -example of an Xcode project for iOS which uses Avian. - * _default:_ false - - * `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 - - * `heapdump` - if true, implement avian.Machine.dumpHeap(String), -which, when called, will generate a snapshot of the heap in a -simple, ad-hoc format for memory profiling purposes. See -heapdump.cpp for details. - * _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 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 - -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/i386 would be built in -_build/linux-i386-debug-bootimage_. This allows you to build with -several different sets of options independently and even -simultaneously without doing a clean build each time. - -If you are compiling for Windows, you may either cross-compile using -MinGW or build natively on Windows under MSYS or Cygwin. - -#### Installing MSYS: - - __1.__ Download and install the current MinGW and MSYS packages from - mingw.org, selecting the C and C++ compilers when prompted. Use the - post-install script to create the filesystem link to the compiler. - - __2.__ Download GNU Make 3.81 from the MSYS download page - (make-3.81-MSYS-1.0.11-2.tar.bz2) and extract the tar file into - _e.g. c:/msys/1.0_. - -#### Installing Cygwin: - - __1.__ Download and run setup.exe from [cygwin's website](http://www.cygwin.com), 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 git@github.com: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 git@github.com: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. - -The MSVC build has been tested with Visual Studio Express Edition -versions 8, 9, and 10. Other versions may also work. - -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 9.0/Common7/IDE:/cygdrive/c/Program Files/Microsoft Visual Studio 9.0/VC/BIN:/cygdrive/c/Program Files/Microsoft Visual Studio 9.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 9.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 9.0\VC\LIB;" - $ export VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 9.0\VC" - $ export LIB="C:\Program Files\Microsoft Visual Studio 9.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v6.0A\lib;" - $ export INCLUDE="C:\Program Files\Microsoft Visual Studio 9.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 9.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. To run an -application in this configuration, you'll need to make sure the VM is -in your library search path. For example: - - $ LD_LIBRARY_PATH=build/linux-x86_64-openjdk \ - 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 -_git://oss.readytalk.com/avian-swt-examples.git_ 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](https://wikis.oracle.com/display/OpenJDK/Mac+OS+X+Port). - -_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](http://weblogs.java.net/blog/simonis/archive/2011/10/28/yaojowbi-yet-another-openjdk-windows-build-instruction). - -_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. - - -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 <embedded-jar-main.cpp <("-Xbootclasspath:[bootJar]"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(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 -D_JNI_IMPLEMENTATION_ -c embedded-jar-main.cpp \ - -o main.o - -__on Windows:__ - - $ g++ -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 - $ g++ hello.exp *.o -L../../win32/lib -lmingwthrd -lm -lz -lws2_32 \ - -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/i386. -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-i386-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-i386-bootimage/classpath.jar) - -__3.__ Build the Java code and add it to stage1. - - $ cat >Hello.java <hello.pro <bootimage-main.cpp <("-Davian.bootimage=bootimageBin"); - - options[1].optionString - = const_cast("-Davian.codeimage=codeimageBin"); - - JavaVM* vm; - void* env; - JNI_CreateJavaVM(&vm, &env, &vmArgs); - JNIEnv* e = static_cast(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. From ab0310d781f11b119909ff2f2d3f1f12e14eff58 Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Mon, 7 Jan 2013 09:29:31 -0700 Subject: [PATCH 11/37] Added the travis.yml file --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..954dbe7ab0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: java +jdk: + - openjdk6 + - openjdk7 + - oraclejdk7 \ No newline at end of file From 3010aa13a5599229bb23314b38f7ce828c65a870 Mon Sep 17 00:00:00 2001 From: terekcampbell Date: Mon, 7 Jan 2013 09:38:02 -0700 Subject: [PATCH 12/37] Updated README for Travis CI --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d27542f88..60dd05c4cf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Avian - A lightweight Java Virtual Machine (JVM) ================================================ -[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) +[![Build Status](https://travis-ci.org/terekcampbell/avian.png?branch=master)](https://travis-ci.org/terekcampbell/avian) Quick Start ----------- @@ -729,4 +729,4 @@ 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. \ No newline at end of file +The Avian project is not affiliated with Oracle. From ff08a658fe1226bf4b8ff23e4899ab2427b97d1c Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Mon, 7 Jan 2013 09:39:25 -0700 Subject: [PATCH 13/37] Further changes to travis.yml --- .travis.yml | 6 +----- README.md | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 954dbe7ab0..f5c99a7f66 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1 @@ -language: java -jdk: - - openjdk6 - - openjdk7 - - oraclejdk7 \ No newline at end of file +language: java \ No newline at end of file diff --git a/README.md b/README.md index 8d27542f88..a22229755e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Avian - A lightweight Java Virtual Machine (JVM) ================================================ -[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) +[![Build Status](https://travis-ci.org/terekcampbell/avian.png?branch=master)](https://travis-ci.org/terekcampbell/avian) Quick Start ----------- From d53920a188c0b3f3c61f692566357e44a82a3826 Mon Sep 17 00:00:00 2001 From: Terek Campbell Date: Mon, 7 Jan 2013 10:57:50 -0700 Subject: [PATCH 14/37] Edit README.md to work with ReadyTalk's Travis CI --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60dd05c4cf..f01811b4e1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Avian - A lightweight Java Virtual Machine (JVM) ================================================ -[![Build Status](https://travis-ci.org/terekcampbell/avian.png?branch=master)](https://travis-ci.org/terekcampbell/avian) +[![Build Status](https://travis-ci.org/ReadyTalk/avian.png?branch=master)](https://travis-ci.org/ReadyTalk/avian) Quick Start ----------- From 548a40ea3af42ce03b4fff09e7e5faeba667ec3a Mon Sep 17 00:00:00 2001 From: Seth Goings Date: Mon, 7 Jan 2013 11:36:34 -0700 Subject: [PATCH 15/37] Update .travis.yml Use make to build this project in Travis instead of the Java default --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f5c99a7f66..f9d431f824 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1 +1,2 @@ -language: java \ No newline at end of file +language: c++ +script: "make test" From 6e6ee31128229b4333a7cbdf9f2614ac3b4859b2 Mon Sep 17 00:00:00 2001 From: Seth Goings Date: Mon, 7 Jan 2013 11:37:01 -0700 Subject: [PATCH 16/37] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f9d431f824..e2d152d5f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,2 @@ -language: c++ +language: cpp script: "make test" From ccbdd6723a3b0608ef4039d78467db6352d832d0 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Jan 2013 14:08:07 -0700 Subject: [PATCH 17/37] specify CodeCapacity based on target arch, not build arch --- src/bootimage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index 492366f6c2..ed7a271cb2 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1991,7 +1991,8 @@ main(int ac, const char** av) // in a branch instruction for the target architecture (~32MB on // PowerPC and ARM). When that limitation is removed, we'll be able // to specify a capacity as large as we like here: -#if (defined ARCH_x86_64) || (defined ARCH_x86_32) +#if (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64) \ + || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_32) const unsigned CodeCapacity = 128 * 1024 * 1024; #else const unsigned CodeCapacity = 30 * 1024 * 1024; From 2a45a5919ce4a933caae6336e48e9495c1c155d8 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 19 Jan 2013 14:10:31 -0700 Subject: [PATCH 18/37] return XToolkit from iOS getPreferredToolkit stub This is necessary to prevent an NPE in Hashtable.put when System.initProperites tries to put a null value in the map for java.awt.graphicsenv. --- src/openjdk/my_java_props_macosx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openjdk/my_java_props_macosx.c b/src/openjdk/my_java_props_macosx.c index 8a1850010f..19de63cb35 100644 --- a/src/openjdk/my_java_props_macosx.c +++ b/src/openjdk/my_java_props_macosx.c @@ -3,7 +3,7 @@ PreferredToolkit getPreferredToolkit() { - return unset; + return XToolkit; } void From 0adccdc99c80f76833ee696438150672a17c0091 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 24 Jan 2013 12:12:00 -0700 Subject: [PATCH 19/37] return unadorned filename from JVM_GetSystemPackage Package.defineSystemPackage expects a filename, not a URL. --- src/classpath-openjdk.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 4842ab8581..348a739cfe 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -746,7 +746,20 @@ class MyClasspath : public Classpath { byteArrayEqual); object source = classSource(t, class_); - if (source == 0) { + if (source) { + // note that we strip the "file:" prefix, since + // Package.defineSystemPackage expects an unadorned + // filename: + const unsigned PrefixLength = 5; + unsigned sourceNameLength = byteArrayLength(t, source) + - PrefixLength; + THREAD_RUNTIME_ARRAY(t, char, sourceName, sourceNameLength); + memcpy(RUNTIME_ARRAY_BODY(sourceName), + &byteArrayBody(t, source, PrefixLength), + sourceNameLength); + + source = vm::makeByteArray(t, "%s", sourceName); + } else { source = vm::makeByteArray(t, "avian-dummy-package-source"); } From 36eee724c913b6b8ea046a200814b9fcf331ff5b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 24 Jan 2013 12:13:42 -0700 Subject: [PATCH 20/37] check argument types in JVM_InvokeMethod Method.invoke must throw an IllegalArgumentException if it receives the wrong number or types of arguments, and since this isn't done by the OpenJDK class library, we must do it in the VM. --- src/classpath-openjdk.cpp | 53 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 348a739cfe..75c49b9bf7 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -4795,6 +4795,59 @@ jvmInvokeMethod(Thread* t, uintptr_t* arguments) instance = 0; } + if ((args == 0 ? 0 : objectArrayLength(t, *args)) + != methodParameterCount(t, vmMethod)) + { + throwNew(t, Machine::IllegalArgumentExceptionType); + } + + if (methodParameterCount(t, vmMethod)) { + PROTECT(t, vmMethod); + + unsigned specLength = byteArrayLength(t, methodSpec(t, vmMethod)); + THREAD_RUNTIME_ARRAY(t, char, spec, specLength); + memcpy(spec, &byteArrayBody(t, methodSpec(t, vmMethod), 0), specLength); + unsigned i = 0; + for (MethodSpecIterator it(t, spec); it.hasNext();) { + object type; + bool objectType = false; + const char* p = it.next(); + switch (*p) { + case 'Z': type = vm::type(t, Machine::BooleanType); break; + case 'B': type = vm::type(t, Machine::ByteType); break; + case 'S': type = vm::type(t, Machine::ShortType); break; + case 'C': type = vm::type(t, Machine::CharType); break; + case 'I': type = vm::type(t, Machine::IntType); break; + case 'F': type = vm::type(t, Machine::FloatType); break; + case 'J': type = vm::type(t, Machine::LongType); break; + case 'D': type = vm::type(t, Machine::DoubleType); break; + + case 'L': ++ p; + case '[': { + objectType = true; + unsigned nameLength = it.s - p; + THREAD_RUNTIME_ARRAY(t, char, name, nameLength); + memcpy(name, p, nameLength - 1); + name[nameLength - 1] = 0; + type = resolveClass + (t, classLoader(t, methodClass(t, vmMethod)), name); + } break; + + default: + abort(); + } + + object arg = objectArrayBody(t, *args, i++); + if ((arg == 0 and (not objectType)) + or (arg and (not instanceOf(t, type, arg)))) + { + // fprintf(stderr, "%s is not a %s\n", arg ? &byteArrayBody(t, className(t, objectClass(t, arg)), 0) : reinterpret_cast(""), &byteArrayBody(t, className(t, type), 0)); + + throwNew(t, Machine::IllegalArgumentExceptionType); + } + } + } + unsigned returnCode = methodReturnCode(t, vmMethod); THREAD_RESOURCE0(t, { From 844520a4026b2a57e22a67d7880cc12867507156 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 25 Jan 2013 07:57:57 -0700 Subject: [PATCH 21/37] fix embed.cpp build for 64-bit Windows --- src/embed.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/embed.cpp b/src/embed.cpp index a4a32bb6d7..293169ce78 100644 --- a/src/embed.cpp +++ b/src/embed.cpp @@ -17,8 +17,14 @@ #include "embed.h" -extern "C" const uint8_t binary_loader_start[]; -extern "C" const uint8_t binary_loader_end[]; +#ifdef __x86_64__ +# define BINARY_LOADER(x) _binary_loader_##x +#else +# define BINARY_LOADER(x) binary_loader_##x +#endif + +extern "C" const uint8_t BINARY_LOADER(start)[]; +extern "C" const uint8_t BINARY_LOADER(end)[]; __declspec(noreturn) void printUsage(const wchar_t* executableName) @@ -31,8 +37,8 @@ void writeDestinationFile(const wchar_t* filename) { if(FILE* file = _wfopen(filename, L"wb")) { - size_t count = binary_loader_end - binary_loader_start; - if(count == fwrite(binary_loader_start, sizeof(binary_loader_start[0]), count, file)) + size_t count = BINARY_LOADER(end) - BINARY_LOADER(start); + if(count == fwrite(BINARY_LOADER(start), sizeof(BINARY_LOADER(start)[0]), count, file)) { fclose(file); return; From 2131adf3aa2f14172f6372e748a44d468b4abe66 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 25 Jan 2013 08:07:47 -0700 Subject: [PATCH 22/37] fix Windows OpenJDK build --- src/classpath-openjdk.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 75c49b9bf7..a1a13efa22 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -46,7 +46,8 @@ # define O_RDONLY _O_RDONLY -# ifdef AVIAN_OPENJDK_SRC +# if (defined AVIAN_OPENJDK_SRC) \ + || ((defined __x86_64__) && (defined __MINGW32__)) # define EXPORT(x) x # else # define EXPORT(x) _##x @@ -450,9 +451,14 @@ class MyClasspath : public Classpath { // todo: handle other architectures # define LIB_DIR "/lib/i386" #endif + +#ifdef PLATFORM_WINDOWS + sb.append(LIB_DIR); +#else sb.append(LIB_DIR ":"); sb.append(javaHome); sb.append(LIB_DIR "/xawt"); +#endif sb.append('\0'); unsigned tzMappingsOffset = sb.offset; @@ -638,7 +644,9 @@ class MyClasspath : public Classpath { #else // not AVIAN_OPENJDK_SRC expect(t, loadLibrary(t, libraryPath, "verify", true, true)); expect(t, loadLibrary(t, libraryPath, "java", true, true)); +# ifndef PLATFORM_WINDOWS loadLibrary(t, libraryPath, "mawt", true, true); +# endif #endif // not AVIAN_OPENJDK_SRC { object assertionLock = resolveField From 1a44ec9eeffbc4b95241277fdc6f95a36639a1ed Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 25 Jan 2013 16:47:31 -0700 Subject: [PATCH 23/37] fix incorrect macro name in bootimage.cpp --- src/bootimage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index ed7a271cb2..edb82b0527 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1992,9 +1992,10 @@ main(int ac, const char** av) // PowerPC and ARM). When that limitation is removed, we'll be able // to specify a capacity as large as we like here: #if (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64) \ - || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_32) + || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) const unsigned CodeCapacity = 128 * 1024 * 1024; #else +# error "wtf?" const unsigned CodeCapacity = 30 * 1024 * 1024; #endif From 70a7a50a498a108b46844223eaeef1afd46ade52 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 17:15:15 -0700 Subject: [PATCH 24/37] fix int-to-long conversions from memory on x86_32 The instruction for 32-bit-to-64-bit sign extension on x86_32 requires that the input value be placed in EAX and the sign extension in EDX. However, the compiler can get confused if the input value is in memory addressed via one of those registers and doesn't know how to move it. This patch works around that limitation by doing the move explicitly in MemoryEvent::compile if necessary. --- src/compiler.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 8e118008bb..988cdb33fb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2003,6 +2003,13 @@ class MemorySite: public Site { } } + bool conflicts(const SiteMask& mask) { + return (mask.typeMask & (1 << RegisterOperand)) != 0 + and (((1 << base) & mask.registerMask) == 0 + or (index != NoRegister + and ((1 << index) & mask.registerMask) == 0)); + } + virtual bool match(Context* c, const SiteMask& mask) { assert(c, acquired); @@ -4574,8 +4581,20 @@ class OperationEvent: public Event { void appendOperation(Context* c, Operation op) { - append - (c, new(c->zone) OperationEvent(c, op)); + append(c, new(c->zone) OperationEvent(c, op)); +} + +void +moveIfConflict(Context* c, Value* v, MemorySite* s) +{ + if (v->reads) { + SiteMask mask(1 << RegisterOperand, ~0, AnyFrameIndex); + v->reads->intersect(&mask); + if (s->conflicts(mask)) { + maybeMove(c, v->reads, true, false); + removeSite(c, v, s); + } + } } class MemoryEvent: public Event { @@ -4626,22 +4645,24 @@ class MemoryEvent: public Event { popRead(c, this, index); } - Site* site = memorySite + MemorySite* site = memorySite (c, baseRegister, displacement, indexRegister, scale); - Site* low; + MemorySite* low; if (result->nextWord != result) { - Site* high = site->copyHigh(c); - low = site->copyLow(c); + MemorySite* high = static_cast(site->copyHigh(c)); + low = static_cast(site->copyLow(c)); result->nextWord->target = high; addSite(c, result->nextWord, high); + moveIfConflict(c, result->nextWord, high); } else { low = site; } result->target = low; addSite(c, result, low); + moveIfConflict(c, result, low); } Value* base; From dec2095c6328d39ce7f2c3b9e432aeb72d092ada Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 18:01:34 -0700 Subject: [PATCH 25/37] fix openjdk bootimage cross builds We need to extract the OpenJDK classes into the build classpath directory for the target platform before running the bootimage-generator, or else it won't be able to find the classes. --- makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/makefile b/makefile index f006ba0bf9..46bbd9b8ff 100755 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -MAKEFLAGS = -s +#MAKEFLAGS = -s name = avian version = 0.6 @@ -1158,7 +1158,8 @@ $(static-library): $(vm-objects) $(classpath-objects) $(vm-heapwalk-objects) \ $(ar) cru $(@) $(^) $(ranlib) $(@) -$(bootimage-object) $(codeimage-object): $(bootimage-generator) +$(bootimage-object) $(codeimage-object): $(bootimage-generator) \ + $(build)/classpath.jar $(<) -cp $(classpath-build) -bootimage $(bootimage-object) -codeimage $(codeimage-object) \ -bootimage-symbols _binary_bootimage_bin_start:_binary_bootimage_bin_end \ -codeimage-symbols _binary_codeimage_bin_start:_binary_codeimage_bin_end From 75f5921b3ed2d231d182a5f225a62ff5b7cad3bb Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 20:07:18 -0700 Subject: [PATCH 26/37] revert accidental makefile change --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 46bbd9b8ff..b3cbd88a57 100755 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -#MAKEFLAGS = -s +MAKEFLAGS = -s name = avian version = 0.6 From 67fd7072543e6c100bab2901576d731efcad6f51 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 22:06:53 -0700 Subject: [PATCH 27/37] fix handling of unusual exception handler layout Scala sometimes generates bytecode such that the scope of an exception handler starts at another exception handler, e.g.: Exception table: from to target type 290 372 382 any 382 451 451 any 290 372 451 any Avian's compiler was incorrectly initializing the stack frame for the second handler in this case. This commit fixes the problem. --- src/compiler.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 988cdb33fb..8d0c1bd2f9 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -672,6 +672,8 @@ class Event { virtual bool allExits() { return false; } + virtual Local* locals() { return localsBefore; } + Event* next; Stack* stackBefore; Local* localsBefore; @@ -5183,8 +5185,9 @@ appendSaveLocals(Context* c) class DummyEvent: public Event { public: - DummyEvent(Context* c): - Event(c) + DummyEvent(Context* c, Local* locals): + Event(c), + locals_(locals) { } virtual const char* name() { @@ -5192,6 +5195,12 @@ class DummyEvent: public Event { } virtual void compile(Context*) { } + + virtual Local* locals() { + return locals_; + } + + Local* locals_; }; void @@ -5204,7 +5213,7 @@ appendDummy(Context* c) c->stack = i->stack; c->locals = i->locals; - append(c, new(c->zone) DummyEvent(c)); + append(c, new(c->zone) DummyEvent(c, locals)); c->stack = stack; c->locals = locals; @@ -6449,14 +6458,14 @@ class MyCompiler: public Compiler { Event* e = c.logicalCode[logicalIp]->firstEvent; for (int i = 0; i < static_cast(c.localFootprint); ++i) { - Local* local = e->localsBefore + i; + Local* local = e->locals() + i; if (local->value) { initLocal (1, i, local->value->type == ValueGeneral ? IntegerType : FloatType); } } - linkLocals(&c, e->localsBefore, newLocals); + linkLocals(&c, e->locals(), newLocals); } virtual void storeLocal(unsigned footprint, Operand* src, unsigned index) { From 0c5471d25e98ffba42e23efaa4a7e2bab52d3c6b Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 28 Jan 2013 16:24:08 -0700 Subject: [PATCH 28/37] remove temporary #error used for debugging Sorry, that wasn't supposed to be checked in. --- src/bootimage.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootimage.cpp b/src/bootimage.cpp index edb82b0527..f82e73f9f5 100644 --- a/src/bootimage.cpp +++ b/src/bootimage.cpp @@ -1995,7 +1995,6 @@ main(int ac, const char** av) || (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) const unsigned CodeCapacity = 128 * 1024 * 1024; #else -# error "wtf?" const unsigned CodeCapacity = 30 * 1024 * 1024; #endif From b1eb4b9718b193446ab8403f2cc0235f4be53e10 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Wed, 30 Jan 2013 04:21:11 +0100 Subject: [PATCH 29/37] Adds code to get the Scala REPL working --- classpath/java/io/File.java | 7 ++- classpath/java/lang/Integer.java | 23 +++++++- classpath/java/lang/Long.java | 8 ++- classpath/java/math/BigInteger.java | 44 +++++++++++++++ classpath/java/math/MathContext.java | 71 +++++++++++++++++++++++++ classpath/java/math/RoundingMode.java | 36 +++++++++++++ classpath/java/util/jar/Attributes.java | 27 ++++++++++ 7 files changed, 213 insertions(+), 3 deletions(-) create mode 100644 classpath/java/math/BigInteger.java create mode 100644 classpath/java/math/MathContext.java create mode 100644 classpath/java/math/RoundingMode.java create mode 100644 classpath/java/util/jar/Attributes.java diff --git a/classpath/java/io/File.java b/classpath/java/io/File.java index 187549ebfd..b66aa03ff9 100644 --- a/classpath/java/io/File.java +++ b/classpath/java/io/File.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2012, Avian Contributors +/* Copyright (c) 2008-2013, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -16,6 +16,11 @@ public class File implements Serializable { public static final String separator = FileSeparator; + private static final String PathSeparator + = System.getProperty("path.separator"); + + public static final String pathSeparator = PathSeparator; + // static { // System.loadLibrary("natives"); // } diff --git a/classpath/java/lang/Integer.java b/classpath/java/lang/Integer.java index 8ea8668ddc..9bd399f227 100644 --- a/classpath/java/lang/Integer.java +++ b/classpath/java/lang/Integer.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, Avian Contributors +/* Copyright (c) 2008-2013, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -94,6 +94,27 @@ public final class Integer extends Number implements Comparable { return (double) value; } + public static int signum(int v) { + if (v == 0) return 0; + else if (v > 0) return 1; + else return -1; + } + + // See http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel + public static int bitCount(int v) { + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; + } + + public static int reverseBytes(int v) { + int byte3 = v >>> 24; + int byte2 = (v >>> 8) & 0xFF00; + int byte1 = (v << 8) & 0xFF00; + int byte0 = v << 24; + return (byte0 | byte1 | byte2 | byte3); + } + public static int parseInt(String s) { return parseInt(s, 10); } diff --git a/classpath/java/lang/Long.java b/classpath/java/lang/Long.java index b7569951b7..425e68383a 100644 --- a/classpath/java/lang/Long.java +++ b/classpath/java/lang/Long.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2010, Avian Contributors +/* Copyright (c) 2008-2013, Avian Contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided @@ -126,6 +126,12 @@ public final class Long extends Number implements Comparable { return (double) value; } + public static int signum(long v) { + if (v == 0) return 0; + else if (v > 0) return 1; + else return -1; + } + private static long pow(long a, long b) { long c = 1; for (int i = 0; i < b; ++i) c *= a; diff --git a/classpath/java/math/BigInteger.java b/classpath/java/math/BigInteger.java new file mode 100644 index 0000000000..319b01707b --- /dev/null +++ b/classpath/java/math/BigInteger.java @@ -0,0 +1,44 @@ +/* Copyright (c) 2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.math; + +import java.io.Serializable; + +public class BigInteger implements Serializable { + + private int sign; + private int[] value; + + private BigInteger(int sign, long value) { + this.sign = sign; + int upperBits = (int) (value >>> 32); + if (upperBits == 0) + // Array with one element + this.value = new int[] { (int) value }; + else + // Array with two elements + this.value = new int[] { (int) value, upperBits }; + } + + public static final BigInteger ZERO = new BigInteger(0, 0); + public static final BigInteger ONE = new BigInteger(1, 1); + public static final BigInteger TEN = new BigInteger(1, 10); + + public static BigInteger valueOf(long num) { + int signum = Long.signum(num); + if (signum == 0) + return BigInteger.ZERO; + else if (signum > 0) + return new BigInteger(signum, num); + else + return new BigInteger(signum, -num); + } +} diff --git a/classpath/java/math/MathContext.java b/classpath/java/math/MathContext.java new file mode 100644 index 0000000000..7ff24d8b12 --- /dev/null +++ b/classpath/java/math/MathContext.java @@ -0,0 +1,71 @@ +/* Copyright (c) 2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.math; + +import java.io.Serializable; + +public final class MathContext implements Serializable { + + public static final MathContext DECIMAL32 = new MathContext( 7, RoundingMode.HALF_EVEN); + public static final MathContext DECIMAL64 = new MathContext(16, RoundingMode.HALF_EVEN); + public static final MathContext DECIMAL128 = new MathContext(34, RoundingMode.HALF_EVEN); + public static final MathContext UNLIMITED = new MathContext(0, RoundingMode.HALF_UP); + + private int precision; + private RoundingMode roundingMode; + + public MathContext(int precision, RoundingMode roundingMode) { + if (precision < 0) + throw new IllegalArgumentException(); + if (roundingMode == null) + throw new NullPointerException(); + this.precision = precision; + this.roundingMode = roundingMode; + } + + public MathContext(int precision) { + this(precision, RoundingMode.HALF_UP); + } + + public int getPrecision() { + return precision; + } + + public RoundingMode getRoundingMode() { + return roundingMode; + } + + @Override + public boolean equals(Object that) { + return + (that instanceof MathContext) && + (precision == ((MathContext) that).getPrecision()) && + (roundingMode == ((MathContext) that).getRoundingMode()); + } + + @Override + public int hashCode() { + return + roundingMode.ordinal() | + (precision << 4); + } + + private final static String precisionString = "precision="; + private final static String roundingModeString = " roundingMode="; + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(48); + sb.append(precisionString).append(precision); + sb.append(roundingModeString).append(roundingMode); + return sb.toString(); + } +} diff --git a/classpath/java/math/RoundingMode.java b/classpath/java/math/RoundingMode.java new file mode 100644 index 0000000000..22bfd69757 --- /dev/null +++ b/classpath/java/math/RoundingMode.java @@ -0,0 +1,36 @@ +/* Copyright (c) 2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.math; + +public enum RoundingMode { + + UP (0), + DOWN (1), + CEILING (2), + FLOOR (3), + HALF_UP (4), + HALF_DOWN (5), + HALF_EVEN (6), + UNNECESSARY(7); + + RoundingMode(int rm) { + roundingMode = rm; + } + + private final int roundingMode; + + public static RoundingMode valueOf(int roundingMode) { + final RoundingMode[] values = values(); + if (roundingMode < 0 || roundingMode >= values.length) + throw new IllegalArgumentException(); + return values[roundingMode]; + } +} diff --git a/classpath/java/util/jar/Attributes.java b/classpath/java/util/jar/Attributes.java new file mode 100644 index 0000000000..806fdb5b98 --- /dev/null +++ b/classpath/java/util/jar/Attributes.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2013, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.jar; + +public class Attributes { + public static class Name { + private final String name; + + private static final int MAX_NAME_LENGTH = 70; + + public Name(String s) { + int len = s.length(); + if (len == 0 || len > MAX_NAME_LENGTH) + throw new IllegalArgumentException(); + + name = s; + } + } +} From 1db67e463f6fb39e616e02819b3b949fc0e3c56e Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Sun, 3 Feb 2013 15:39:31 +0100 Subject: [PATCH 30/37] Add Class#isEnum and improve error handling in Enum.valueOf --- classpath/java/lang/Class.java | 9 +++++++-- classpath/java/lang/Enum.java | 9 ++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index eb183260d6..dcef601f12 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -37,7 +37,8 @@ import java.security.Permissions; import java.security.AllPermission; public final class Class implements Type, AnnotatedElement { - private static final int PrimitiveFlag = 1 << 5; + private static final int PrimitiveFlag = 1 << 5; + private static final int EnumFlag = 1 << 14; public final VMClass vmClass; @@ -555,6 +556,10 @@ public final class Class implements Type, AnnotatedElement { return (vmClass.vmFlags & PrimitiveFlag) != 0; } + public boolean isEnum() { + return getSuperclass() == Enum.class && (vmClass.flags & EnumFlag) != 0; + } + public URL getResource(String path) { if (! path.startsWith("/")) { String name = new String @@ -626,7 +631,7 @@ public final class Class implements Type, AnnotatedElement { for (VMClass c = vmClass; c != null; c = c.super_) { if (c.addendum != null && c.addendum.annotationTable != null) { Classes.link(c, c.loader); - + Object[] table = (Object[]) c.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; diff --git a/classpath/java/lang/Enum.java b/classpath/java/lang/Enum.java index 8d0d4756b0..a70b2074a9 100644 --- a/classpath/java/lang/Enum.java +++ b/classpath/java/lang/Enum.java @@ -30,7 +30,9 @@ public abstract class Enum> implements Comparable { } public static > T valueOf(Class enumType, String name) { - if (name == null) throw new NullPointerException(); + if (name == null) throw new NullPointerException("name"); + if (!enumType.isEnum()) + throw new IllegalArgumentException(enumType.getCanonicalName() + " is not an enum."); try { Method method = enumType.getMethod("values"); @@ -41,10 +43,11 @@ public abstract class Enum> implements Comparable { } } } catch (Exception ex) { - throw new RuntimeException(ex); + // Cannot happen + throw new Error(ex); } - throw new IllegalArgumentException(name); + throw new IllegalArgumentException(enumType.getCanonicalName() + "." + name + " is not an enum constant."); } public int ordinal() { From 1890e348fb7d596c75051329f5f0059c20419a8d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 14:09:29 -0700 Subject: [PATCH 31/37] fix handling of classe, method, and field names with non-ASCII characters --- src/classpath-openjdk.cpp | 4 +- src/machine.cpp | 80 ++++++++++++++++++++++++++++++++++----- src/machine.h | 3 ++ src/stream.h | 30 +++++++++++---- test/Misc.java | 13 +++++++ 5 files changed, 113 insertions(+), 17 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index a1a13efa22..9869538cf6 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -504,6 +504,8 @@ class MyClasspath : public Classpath { object charArray = makeCharArray(t, length); for (int i = 0; i < length; ++i) { + expect(t, (byteArrayBody(t, array, offset + i) & 0x80) == 0); + charArrayBody(t, charArray, i) = byteArrayBody(t, array, offset + i); } @@ -5039,7 +5041,7 @@ jvmConstantPoolGetUTF8At(Thread* t, uintptr_t* arguments) jobject pool = reinterpret_cast(arguments[0]); jint index = arguments[1]; - object array = singletonObject(t, *pool, index - 1); + object array = parseUtf8(t, singletonObject(t, *pool, index - 1)); return reinterpret_cast (makeLocalReference diff --git a/src/machine.cpp b/src/machine.cpp index 828de31fc0..0d0ad96865 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -727,7 +727,7 @@ finalizeObject(Thread* t, object o, const char* name) } unsigned -readByte(Stream& s, unsigned* value) +readByte(AbstractStream& s, unsigned* value) { if (*value == NoByte) { return s.read1(); @@ -739,8 +739,9 @@ readByte(Stream& s, unsigned* value) } object -parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, - unsigned sourceIndex, unsigned byteA, unsigned byteB) +parseUtf8NonAscii(Thread* t, AbstractStream& s, object bytesSoFar, + unsigned byteCount, unsigned sourceIndex, unsigned byteA, + unsigned byteB) { PROTECT(t, bytesSoFar); @@ -792,7 +793,7 @@ parseUtf8NonAscii(Thread* t, Stream& s, object bytesSoFar, unsigned byteCount, } object -parseUtf8(Thread* t, Stream& s, unsigned length) +parseUtf8(Thread* t, AbstractStream& s, unsigned length) { object value = makeByteArray(t, length + 1); unsigned vi = 0; @@ -830,6 +831,14 @@ parseUtf8(Thread* t, Stream& s, unsigned length) return value; } +object +makeByteArray(Thread* t, Stream& s, unsigned length) +{ + object value = makeByteArray(t, length + 1); + s.read(reinterpret_cast(&byteArrayBody(t, value, 0)), length); + return value; +} + void removeByteArray(Thread* t, object o) { @@ -885,10 +894,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) case CONSTANT_Utf8: { if (singletonObject(t, pool, i) == 0) { - object value = parseUtf8(t, s, s.read2()); - if (objectClass(t, value) == type(t, Machine::ByteArrayType)) { - value = internByteArray(t, value); - } + object value = internByteArray(t, makeByteArray(t, s, s.read2())); set(t, pool, SingletonBody + (i * BytesPerWord), value); if(DebugClassReader) { @@ -916,7 +922,7 @@ parsePoolEntry(Thread* t, Stream& s, uint32_t* index, object pool, unsigned i) unsigned si = s.read2() - 1; parsePoolEntry(t, s, index, pool, si); - object value = singletonObject(t, pool, si); + object value = parseUtf8(t, singletonObject(t, pool, si)); value = t->m->classpath->makeString (t, value, 0, cast(value, BytesPerWord) - 1); value = intern(t, value); @@ -4886,6 +4892,62 @@ parseUtf8(Thread* t, const char* data, unsigned length) return ::parseUtf8(t, s, length); } +object +parseUtf8(Thread* t, object array) +{ + for (unsigned i = 0; i < byteArrayLength(t, array) - 1; ++i) { + if (byteArrayBody(t, array, i) & 0x80) { + goto slow_path; + } + } + + return array; + + slow_path: + class Client: public Stream::Client { + public: + Client(Thread* t): t(t) { } + + virtual void handleError() { + // vm::abort(t); + } + + private: + Thread* t; + } client(t); + + class MyStream: public AbstractStream { + public: + class MyProtector: public Thread::Protector { + public: + MyProtector(Thread* t, MyStream* s): + Protector(t), s(s) + { } + + virtual void visit(Heap::Visitor* v) { + v->visit(&(s->array)); + } + + MyStream* s; + }; + + MyStream(Thread* t, Client* client, object array): + AbstractStream(client, byteArrayLength(t, array) - 1), + array(array), + protector(t, this) + { } + + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) { + memcpy(dst, &byteArrayBody(protector.t, array, offset), size); + } + + object array; + MyProtector protector; + } s(t, &client, array); + + return ::parseUtf8(t, s, byteArrayLength(t, array) - 1); +} + object getCaller(Thread* t, unsigned target, bool skipMethodInvoke) { diff --git a/src/machine.h b/src/machine.h index f71788572d..08eab4c894 100644 --- a/src/machine.h +++ b/src/machine.h @@ -2525,6 +2525,9 @@ emptyMethod(Thread* t, object method) object parseUtf8(Thread* t, const char* data, unsigned length); +object +parseUtf8(Thread* t, object array); + object parseClass(Thread* t, object loader, const uint8_t* data, unsigned length, Machine::Type throwType = Machine::NoClassDefFoundErrorType); diff --git a/src/stream.h b/src/stream.h index a08bf3b1a0..a46ad315d8 100644 --- a/src/stream.h +++ b/src/stream.h @@ -15,15 +15,15 @@ namespace vm { -class Stream { +class AbstractStream { public: class Client { public: virtual void handleError() = 0; }; - Stream(Client* client, const uint8_t* data, unsigned size): - client(client), data(data), size(size), position_(0) + AbstractStream(Client* client, unsigned size): + client(client), size(size), position_(0) { } unsigned position() { @@ -42,13 +42,13 @@ class Stream { } } - void read(uint8_t* data, unsigned size) { + void read(uint8_t* dst, unsigned size) { if (size > this->size - position_) { - memset(data, 0, size); + memset(dst, 0, size); client->handleError(); } else { - memcpy(data, this->data + position_, size); + copy(dst, position_, size); position_ += size; } } @@ -85,13 +85,29 @@ class Stream { return read8(); } + protected: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) = 0; + private: Client* client; - const uint8_t* data; unsigned size; unsigned position_; }; +class Stream: public AbstractStream { + public: + Stream(Client* client, const uint8_t* data, unsigned size): + AbstractStream(client, size), data(data) + { } + + private: + virtual void copy(uint8_t* dst, unsigned offset, unsigned size) { + memcpy(dst, data + offset, size); + } + + const uint8_t* data; +}; + } // namespace vm #endif//STREAM_H diff --git a/test/Misc.java b/test/Misc.java index 450f23d2b0..620897332f 100644 --- a/test/Misc.java +++ b/test/Misc.java @@ -1,4 +1,12 @@ public class Misc { + private static class μClass { + public int μField; + + public void μMethod(int i) { + μField = i; + } + } + private interface Bar { public int baz(); } @@ -237,5 +245,10 @@ public class Misc { System.out.println(new char[] { 'h', 'i' }); expect(! (((Object) new int[0]) instanceof Object[])); + + { μClass μInstance = new μClass(); + μInstance.μMethod(8933); + expect(μInstance.μField == 8933); + } } } From 80c8940b7f19dbb4394d9dfd07b2475296173c49 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:18:32 -0700 Subject: [PATCH 32/37] ensure joining threads are always notified when a thread exits Previously, we'd only do this if the thread exited without throwing an exception. Now we do it regardless. --- src/classpath-openjdk.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 9869538cf6..49750e7fb7 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -604,15 +604,21 @@ class MyClasspath : public Classpath { virtual void runThread(Thread* t) { + // force monitor creation so we don't get an OutOfMemory error + // later when we try to acquire it: + objectMonitor(t, t->javaThread, true); + + THREAD_RESOURCE0(t, { + vm::acquire(t, t->javaThread); + t->flags &= ~Thread::ActiveFlag; + vm::notifyAll(t, t->javaThread); + vm::release(t, t->javaThread); + }); + object method = resolveMethod (t, root(t, Machine::BootLoader), "java/lang/Thread", "run", "()V"); t->m->processor->invoke(t, method, t->javaThread); - - acquire(t, t->javaThread); - t->flags &= ~Thread::ActiveFlag; - notifyAll(t, t->javaThread); - release(t, t->javaThread); } virtual void From 3db9e73aa10870ba37d26edfcd8ea9907ddac709 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:19:35 -0700 Subject: [PATCH 33/37] fix GC safety issues in classpath-openjdk.cpp --- src/classpath-openjdk.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 49750e7fb7..bf1dee5050 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -2376,6 +2376,8 @@ makeJmethod(Thread* t, object vmMethod, int index) if (addendum) { signature = addendumSignature(t, addendum); if (signature) { + PROTECT(t, addendum); + signature = t->m->classpath->makeString (t, signature, 0, byteArrayLength(t, signature) - 1); } @@ -2443,6 +2445,8 @@ makeJconstructor(Thread* t, object vmMethod, int index) if (addendum) { signature = addendumSignature(t, addendum); if (signature) { + PROTECT(t, addendum); + signature = t->m->classpath->makeString (t, signature, 0, byteArrayLength(t, signature) - 1); } @@ -2508,6 +2512,8 @@ makeJfield(Thread* t, object vmField, int index) if (addendum) { signature = addendumSignature(t, addendum); if (signature) { + PROTECT(t, addendum); + signature = t->m->classpath->makeString (t, signature, 0, byteArrayLength(t, signature) - 1); } From 23bb2e87433b5dd8db56c19891824b6e42a81c37 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:20:53 -0700 Subject: [PATCH 34/37] force a GC in allocate3 if the heap limit has been exceeded Otherwise, we'll throw an OOME even though there may be enough unreachable objects eligible for collection to get back below the limit. --- src/machine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/machine.cpp b/src/machine.cpp index 0d0ad96865..7986a5be78 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3519,7 +3519,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, break; } - if (t->heap == 0) { + if (t->heap == 0 or t->m->heap->limitExceeded()) { // fprintf(stderr, "gc"); // vmPrintTrace(t); collect(t, Heap::MinorCollection); From e8f8ebdc67a4309ce43e94c1e826bf55159a8e22 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 15:53:36 -0700 Subject: [PATCH 35/37] fail quickly if an object allocation cannot be satisfied Previously, we would blithely exceed the heap ceiling and force the next allocation to deal with the problem, including a major GC and possible OutOfMemoryError. As of this commit, we throw an error immediately if we find that the allocation will push us over the ceiling. --- src/heap.cpp | 44 +++++++++++++++++++++++++++++++++----------- src/heap.h | 10 +++++----- src/machine.cpp | 32 ++++++++++++++++++++------------ src/machine.h | 4 ++-- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/src/heap.cpp b/src/heap.cpp index 2dc23e904e..0cc13ba7dc 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -1895,21 +1895,43 @@ class MyHeap: public Heap { local::collect(&c); } - virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, - bool objectMask, unsigned* totalInBytes) + void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask, unsigned* totalInBytes, + Fixie** handle, bool immortal) { - *totalInBytes = Fixie::totalSize(sizeInWords, objectMask); - return (new (allocator->allocate(*totalInBytes)) - Fixie(&c, sizeInWords, objectMask, &(c.fixies), false))->body(); + *totalInBytes = 0; + + if (limitExceeded()) { + return 0; + } + + unsigned total = Fixie::totalSize(sizeInWords, objectMask); + void* p = allocator->tryAllocate(total); + if (p == 0) { + return 0; + } else if (limitExceeded()) { + allocator->free(p, total); + return 0; + } else { + *totalInBytes = total; + return (new (p) Fixie(&c, sizeInWords, objectMask, handle, immortal)) + ->body(); + } } - virtual void* allocateImmortalFixed(Allocator* allocator, - unsigned sizeInWords, bool objectMask, - unsigned* totalInBytes) + virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask, unsigned* totalInBytes) { - *totalInBytes = Fixie::totalSize(sizeInWords, objectMask); - return (new (allocator->allocate(*totalInBytes)) - Fixie(&c, sizeInWords, objectMask, 0, true))->body(); + return tryAllocateFixed + (allocator, sizeInWords, objectMask, totalInBytes, &(c.fixies), false); + } + + virtual void* tryAllocateImmortalFixed(Allocator* allocator, + unsigned sizeInWords, bool objectMask, + unsigned* totalInBytes) + { + return tryAllocateFixed + (allocator, sizeInWords, objectMask, totalInBytes, 0, true); } bool needsMark(void* p) { diff --git a/src/heap.h b/src/heap.h index 0ee4699914..2a6734438d 100644 --- a/src/heap.h +++ b/src/heap.h @@ -62,11 +62,11 @@ class Heap: public Allocator { virtual unsigned limit() = 0; virtual bool limitExceeded() = 0; virtual void collect(CollectionType type, unsigned footprint) = 0; - virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, - bool objectMask, unsigned* totalInBytes) = 0; - virtual void* allocateImmortalFixed(Allocator* allocator, - unsigned sizeInWords, bool objectMask, - unsigned* totalInBytes) = 0; + virtual void* tryAllocateFixed(Allocator* allocator, unsigned sizeInWords, + bool objectMask, unsigned* totalInBytes) = 0; + virtual void* tryAllocateImmortalFixed(Allocator* allocator, + unsigned sizeInWords, bool objectMask, + unsigned* totalInBytes) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void pad(void* p) = 0; virtual void* follow(void* p) = 0; diff --git a/src/machine.cpp b/src/machine.cpp index 7986a5be78..c06d8c8159 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -3531,7 +3531,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, } while (type == Machine::MovableAllocation and t->heapIndex + ceiling(sizeInBytes, BytesPerWord) > ThreadHeapSizeInWords); - + switch (type) { case Machine::MovableAllocation: { return allocateSmall(t, sizeInBytes); @@ -3540,29 +3540,37 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, case Machine::FixedAllocation: { unsigned total; object o = static_cast - (t->m->heap->allocateFixed + (t->m->heap->tryAllocateFixed (allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); - memset(o, 0, sizeInBytes); + if (o) { + memset(o, 0, sizeInBytes); - alias(o, 0) = FixedMark; - - t->m->fixedFootprint += total; - - return o; + alias(o, 0) = FixedMark; + + t->m->fixedFootprint += total; + + return o; + } else { + throw_(t, root(t, Machine::OutOfMemoryError)); + } } case Machine::ImmortalAllocation: { unsigned total; object o = static_cast - (t->m->heap->allocateImmortalFixed + (t->m->heap->tryAllocateImmortalFixed (allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); - memset(o, 0, sizeInBytes); + if (o) { + memset(o, 0, sizeInBytes); - alias(o, 0) = FixedMark; + alias(o, 0) = FixedMark; - return o; + return o; + } else { + throw_(t, root(t, Machine::OutOfMemoryError)); + } } default: abort(t); diff --git a/src/machine.h b/src/machine.h index 08eab4c894..2924a13fb7 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1784,8 +1784,8 @@ class FixedAllocator: public Allocator { s(s), base(base), offset(0), capacity(capacity) { } - virtual void* tryAllocate(unsigned) { - abort(s); + virtual void* tryAllocate(unsigned size) { + return allocate(size); } void* allocate(unsigned size, unsigned padAlignment) { From 5dcf6eae5a96d24fc045bebca8f13d59e18d46a4 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sun, 3 Feb 2013 20:29:24 -0700 Subject: [PATCH 36/37] fix GC safety issue in MyClasspath::updatePackageMap --- src/classpath-openjdk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index bf1dee5050..cab2d85ba0 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -756,6 +756,7 @@ class MyClasspath : public Classpath { RUNTIME_ARRAY_BODY(packageName)[length] = 0; object key = vm::makeByteArray(t, "%s", packageName); + PROTECT(t, key); hashMapRemove (t, root(t, Machine::PackageMap), key, byteArrayHash, From 57a67fb3124d8bd8a2de09ef4311e8a50febd522 Mon Sep 17 00:00:00 2001 From: Simon Ochsenreither Date: Mon, 4 Feb 2013 14:09:02 +0100 Subject: [PATCH 37/37] Fix field names, add getters to j.l.Package --- classpath/java/lang/Package.java | 68 +++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/classpath/java/lang/Package.java b/classpath/java/lang/Package.java index ed1e4e2985..0b4be0d78f 100644 --- a/classpath/java/lang/Package.java +++ b/classpath/java/lang/Package.java @@ -17,34 +17,66 @@ public class Package { private final String implementationTitle; private final String implementationVendor; private final String implementationVersion; - private final String specementationTitle; - private final String specementationVendor; - private final String specementationVersion; + private final String specificationTitle; + private final String specificationVendor; + private final String specificationVersion; private final URL sealed; private final ClassLoader loader; Package(String name, - String implementationTitle, - String implementationVendor, - String implementationVersion, - String specementationTitle, - String specementationVendor, - String specementationVersion, - URL sealed, + String implementationTitle, + String implementationVendor, + String implementationVersion, + String specificationTitle, + String specificationVendor, + String specificationVersion, + URL sealed, ClassLoader loader) { - this.name = name; - this.implementationTitle = implementationTitle; - this.implementationVendor = implementationVendor; + this.name = name; + this.implementationTitle = implementationTitle; + this.implementationVendor = implementationVendor; this.implementationVersion = implementationVersion; - this.specementationTitle = specementationTitle; - this.specementationVendor = specementationVendor; - this.specementationVersion = specementationVersion; - this.sealed = sealed; - this.loader = loader; + this.specificationTitle = specificationTitle; + this.specificationVendor = specificationVendor; + this.specificationVersion = specificationVersion; + this.sealed = sealed; + this.loader = loader; } public String getName() { return name; } + + public String getImplementationTitle() { + return implementationTitle; + } + + public String getImplementationVendor() { + return implementationVendor; + } + + public String getImplementationVersion() { + return implementationVersion; + } + + public String getSpecificationTitle() { + return specificationTitle; + } + + public String getSpecificationVendor() { + return specificationVendor; + } + + public String getSpecificationVersion() { + return specificationVersion; + } + + public boolean isSealed() { + return sealed != null; + } + + public boolean isSealed(URL url) { + return sealed.equals(url); + } }