There's a small optimization in compileDirectInvoke which tries to
avoid generating calls to empty methods. However, this causes
problems for code which uses such a call to ensure a class is
initialized -- if we omit that call, the class may not be
initialized and any side effects of that initialization may not
happen when the program expects them to.
This commit ensures that the compiler only omits empty method calls
when the target class does not need initialization. It also removes
commented-out code in classpath-openjdk.cpp which was responsible for
loading libmawt proactively; that was a hack to get JogAmp to work
before we understood what the real problem was.
Unsafe.compareAndSwapLong was moved from classpath-openjdk.cpp to
builtin.cpp, but the fieldForOffset helper function was not, which
only caused problems when I tried to build for ARM. This commit moves
said helper function, along with Unsafe.getVolatileLong, which also
uses it.
Most of these regressions were simply due to testing a lot more stuff,
esp. annotations and reflection, revealing holes in the Android
compatibility code. There are still some holes, but at least the
suite is passing (except for a fragile test in Serialize.java which I
will open an issue for).
Sorry this is such a big commit; there was more to address than I
initially expected.
Previously, I used a shell script to extract modification date ranges
from the Git history, but that was complicated and unreliable, so now
every file just gets the same year range in its copyright header. If
someone needs to know when a specific file was modified and by whom,
they can look at the Git history themselves; no need to include it
redundantly in the header.
The original implementation was based on the assumption that the
passed class would be the array element type, whereas it is actually
the array type itself.
It may leak file handles under certain circumstances to do nothing in
JVM_UnloadLibrary, but, for now, an empty implementation is more
useful than one that aborts the process.
At one point, loading libmawt ahead of time was necessary to make AWT
work, but recent versions of OpenJDK seem to take care this from Java
code, in which case loading it ahead of time causes trouble, so we
comment it out for now until we exactly when it's needed.
This mainly moves several sun.misc.Unsafe method implementations from
classpath-openjdk.cpp to builtin.cpp so that the Avian and Android
builds can use them.
It also replaces FinalizerReference.finalizeAllEnqueued with a no-op,
since the real implementations assumes too much about how the VM
handles (or delegates) finalization.
The InnerClasses attribute may have entries for classes declared
inside classes we don't care about, so we must check each entry's
outer class reference and make sure it matches the one we do care
about.
The OpenJDK library wants to track and run the shutdown hooks itself
rather than let the VM do it, so we need to tell it when we're
exiting.
Also, in machine.cpp we need to use only the modifiers specified in
the InnerClasses attribute for inner classes rather than OR them with
the flags given at the top level of the class file.
This fixes a couple of tests in the Scala test suite
(run/reflection-modulemirror-toplevel-badpath.scala and
run/reflection-constructormirror-nested-good.scala).
Timezone code was broken in the Android class library bootimage build
because the code we use to intercept loading the tzdata file wasn't
working. The reason is have no way of intercepting static methods at
runtime in the bootimage build without telling the bootimage-generator
we're going to do it ahead of time. So now we do tell it so.
This commit also removes the need to intercept Thread methods since we
can update Thread.vmThread in VMThread.create instead.
In order for a thread to enter the "exclusive" state such that no
other threads are active in the VM, it must wait for all active
threads to enter the "idle" state. In order for this to happen in a
timely manner, threads must check frequently to see if a thread is
waiting to enter the exclusive state. These checks happen at every
memory allocation, wait, sleep, native call, etc. However, if a
thread is in a busy loop that does none of those things, it will block
any other thread from entering that state.
The proper way to address this is to detect such loops (or tail
recursion in tail-call-optimized builds) at compile or interpret time
and insert explicit checks. This hasn't been a high priority thus
far, though, since we had yet to encounter such code in the wild.
Now, however, we find that scala.concurrent.forkjoin.ForkJoinPool.scan
(and possibly some versions of java.util.concurrent.ForkJoinPool.scan,
on which we assume the former is based) has just such a loop.
Fortunately, that loop calls Unsafe.getObjectVolatile, which the VM
implements and thus can treat as a checkpoint. That's the workaround
we use in this patch.
In the OpenJDK library, ThreadGroup maintains an array of all Threads
in that group, so the VM must explicitly remove threads as they exit
or else neither they nor any objects they reference will be eligable
for GC.
This is necessary to avoid name conflicts on various platforms. For
example, iOS has its own util.h, and Windows has a process.h. By
including our version as e.g. "avian/util.h", we avoid confusion with
the system version.
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.
This library is placed in the xawt subdirectory of jre/lib/$arch on
POSIX systems, so it isn't found automatically when third-party
libraries which depend on it are loaded. The simplest way to ensure
that it's found seems to be to just load it when the VM starts up.
The original stub implementation just echoed back its argument, but
that confused URLClassLoader when dealing with sealed JARs --
returning a non-null value for a non-system class from
JVM_GetSystemPackage made URLClassloader think it had already loaded a
class from a package which was supposed to be sealed, resulting in
SecurityExceptions which ultimately triggered NoClassDefFoundErrors.
The solution is to only return non-null values for actual system
classes.
We weren't wrapping exceptions thrown by invoked methods in
InvocationTargetExceptions in JVM_InvokeMethod or
JVM_NewInstanceFromConstructor. Also, JVM_GetCallerClass is supposed
to ignore Method.invoke frames when walking the stack.
The existing code did not handle static field lookups for
synchronization on 32-bit systems, which is necessary because such
systems generally don't support atomic operations on 64-bit values.
set java.vm.version based on makefile version=
in order to display relevant OpenJDK -version information.
Signed-off-by: Matthias Klose <doko@ubuntu.com>
Signed-off-by: Xerxes Rånby <xerxes@zafena.se>
Some apps refuse to run if Runtime.maxMemory returns a value that's
"too small", so our stub implementation returning zero was not
sufficient. Now we return the actual heap size limit in bytes.
sun.misc.Launcher has its own idea about what the application
classloader should be, but we need to override it with the system
classloader created by the VM. This is achieved by running
Launcher.getLauncher (which has the side effect of setting
Thread.contextClassLoader) and then overriding it.
Our implementation uses Object.wait(long) to implement Thread.sleep,
which had the side effect of interpreting zero as infinity. However,
for Thread.sleep, zero just means zero. I assume that doesn't mean
"don't sleep at all", though, or else the app wouldn't have called
Thread.sleep in the first place, so this patch sleeps for one
millisecond when zero is passed -- just enough to yield the processor
for a bit. Thread.yield might be a better choice in this case, but I
assume the app would have called that directly if that's what it
wanted.
OpenJDK 7 has refactored this code relative to OpenJDK 6, and now
FontManager is an interface, with SunFontManager providing a (partial)
implementation.
On the ARM platform, Avian compiled to use OpenJDK gets this error on
startup:
java/lang/UnsatisfiedLinkError: no zip in java.library.path
at java/lang/ClassLoader.loadLibrary (line 1860)
at java/lang/Runtime.loadLibrary0 (line 845)
at java/lang/System.loadLibrary (line 1084)
at java/lang/System.initializeSystemClass (line 1145)
Using strace shows why:
[pid 22431]
stat64("/usr/lib/jvm/java-7-openjdk-armhf/jre/lib/i386/libzip.so",
0xbee377e0) = -1 ENOENT (No such file or directory)
The attached patch uses "arm" instead of "i386" in that path. This fixes the
problem.
sun.misc.Unsafe now has two native getByte methods: one which takes a
long and another which takes an Object and a long. Thus, we need to
decorate each version with its parameter signature so we don't
accidentally call the wrong one at runtime.
As of the latest code from the jdk7u-dev Mercurial repository,
java.lang.String no longer has offset or length fields. Instead, the
content fits exactly into the backing char array, so offset is
implicitly zero and length is the length of the array. The VM
previously relied on those fields being present, whereas this commit
handles the case where they are not.
In addition, I've made some changes to openjdk-src.mk to ensure that
we can build against both a stock OpenJDK 7 and an IcedTea-patched
version.
The JRE lib dir for OpenJDK 7 on OS X seems to be just "lib", not
e.g. "lib/amd64" by default, so we use that now. Also, the default
library compatibility version for libjvm.dylib is 0.0.0, but OpenJDK
wants 1.0.0, so we set it explicitly.
The bug here is that when a thread exits and becomes a "zombie", the
OS resources associated with it are not necessarily released until we
actually join and dispose of that thread. Since that only happens
during garbage collection, and collection normally only happens in
response to heap memory pressure, there's no guarantee that we'll GC
frequently enough to clean up zombies promptly and avoid running out
of resources.
The solution is to force a GC whenever we start a new thread and there
are at least N zombies waiting to be disposed, where N=16 for now.
We never define atomicCompareAndSwap64 for ARM or PowerPC, and
apparently only very recent ARM chips support it, so we must fall back
to synchronization-based emulation.