An inner class has two sets of modifier flags: one is declared in the
usual place in the class file and the other is part of the
InnerClasses attribute. Not only is that redundant, but they can
contradict, and the VM can't just pick one and roll with it. Instead,
Class.getModifiers must return the InnerClasses version, whereas
reflection must check the top-level version. So even if
Class.getModifiers says the class is protected, it might still be
public for the purpose of reflection depending on what the
InnerClasses attribute says. Crazy? Yes.
When calculating field offsets in the bootimage generator, we failed
to consider alignment at inheritence boundaries (i.e. the last field
inherited by from a superclass should be followed by enough padding to
align the first non-inherited field at a machine word boundary). This
led to a mismatch between native code and Java code in terms of class
layouts, including that of java.lang.reflect.Method.
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.
Method.invoke should initialize its class before invoking the method,
throwing an ExceptionInInitializerError if it fails, without wrapping
said error in an InvocationTargetException.
Also, we must initialize ExceptionInInitializerError.exception when
throwing instances from the VM, since OpenJDK's
ExceptionInInitializerError.getCause uses the exception field, not the
cause field.
When creating an object array with more than two dimensions, the
component type was erroneously set to the base type, not the array
type of one less dimension.
This prevented Collection<Class[]>#toArray(Class[][]) from working
properly.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
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.
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.
We must be in the Active state, not the Exclusive state when calling
this method since it may execute arbitrary Java code. This fixes an
assertion failure in makeNew.
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).
Objects which are eligable for finalization must be retained until
after their finalize methods are called. However, the VM must
determine the entire set of such objects before retaining any of them;
otherwise the process of retaining a given object may cause others to
become reachable and thus be considered ineligible for finalization
even though they are only reachable via other finalizable objects.
The end result of this mistake is that only a few of the objects which
are finalizable will be recognized at each GC cycle, so it requires
many such cycles to find them all, and if new objects become
finalizable at a faster rate, the VM will never catch up and
eventually run out of memory.
This patch fixes the above mistake and also includes tuning to
minimize the need for GC in low memory situations.
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.
Previously, if you forgot to use RUNTIME_ARRAY_BODY to reference an
array declared with (THREAD_)RUNTIME_ARRAY, you wouldn't get a
compiler error until you tried to build on e.g. MSVC, where
runtime-sized stack arrays aren't supported. This change ensures you
find out regardless of what compiler you're using, which ought to
protect us from regressions going forward.
We must use separate va_start/va_end pairs for each call to vsnprintf
on Linux and possibly other platforms in order to avoid a crash.
Also, we need to give it room to null terminate the string at the
right point.
When GetStringCritical or GetPrimitiveArrayCritical are called, the VM
cannot risk new Java heap allocations until the corresponding release
method is called because allocations may result in GC, which cannot
happen while a string or array is pinned in memory. We already have a
check for this latter in the footprint function used during GC, but
it's best to catch the problem as early as possible.
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.
Commit c918cbc added this reference to ensure
sun.misc.Unsafe.getLongVolatile could be implemented efficiently on
32-bit platforms. However, I neglected to ensure the reference was
updated to point to the final class instance instead of the temporary
one used in parseClass. This led to extra memory usage and
inconsistent locking behavior, plus broken bootimage builds.
If we don't clear these references, we risk finalizing objects which
can still be reached by one of the special reference types.
It's a bit of a chicken-and-egg problem. We need to visit finalizable
objects before visiting weak references, since some of the weak
references and/or their targets may become reachable once the
finalizable objects are visited. However, that ordering means we have
no efficient way of distinguishing between objects which are reachable
from one or more normal GC roots and those which are only reachable
via the finalization queue. The solution is to clear all weak
references to finalizable objects before visiting them.