RFR (S) 8150465: Unsafe methods to produce uninitialized arrays

John Rose john.r.rose at oracle.com
Fri Feb 26 08:01:22 UTC 2016


On Feb 25, 2016, at 12:10 AM, Aleksey Shipilev <aleksey.shipilev at oracle.com> wrote:
> 
>> Yes, primitive arrays are fine if the header is correct. In this case
>> changes are fine but you may need to add a check in
>> inline_unsafe_newArray() that it is only primitive types.
> 
> Alas, the class argument may not be constant, and so we would need a
> runtime check there, which would duplicate the check we already have in
> Unsafe.java. I'd prefer to follow the upcoming pattern in Mikael's
> Unsafe cleanup with making as much checks on Java side.

Yes, follow that pattern.  In unsafe.cpp, you should use an assert
(or guarantee) to back up the Java-level checks.  The effect of the
assert is to help diagnose any failure of the Java-level checks.

The compiler intrinsic does not need the double-checking.
Rather, it should run AFAP (as fast as possible) under the
assumption that the Java-level checks have run or don't apply.


On Feb 25, 2016, at 11:01 PM, Aleksey Shipilev <aleksey.shipilev at oracle.com> wrote:

> But if you accept the premise that Unsafe.allocateUninitializedArray is
> wrong because it can leak data from previous allocation if used
> incorrectly, then you should equally accept that compilers should not do
> the same automatic optimization too. Even more so, because the compiler
> code is much harder to audit for these mistakes; and programmers *do*
> make mistakes in that complicated compiler code.

Exactly right.  Unsafe is the "in your face" way to do the same kind of
shady stuff that (otherwise) the C runtime or the JIT IR transforms would
have to do.  In many cases, the necessary audits and proofs are safer
and easier to accomplish when looking at Java code than when looking
at C code (behind a JNI mask) or JIT IR transforms (which nobody
fully understands).  Unsafe is a frank admission that sometimes the
barn needs sweeping, and that it might as well be swept in the daylight.
We don't sit around in the living room pretending we can't smell it.

About the javadoc:

>      * This method is suitable for special high-performance code
>      * that is known to overwrite the array contents right after the allocation.

I suggest pounding harder on this warning:

> In fact, users of this method are required to overwrite the initial (garbage) array
> contents before allowing untrusted code, or code in other threads, to observe
> the reference to the newly allocated array.  In addition, the publication of the
> array reference must be safe according to the JMM.

Suggesting:  Provide a second function to ensure the safe publication,
and require users of aUA to call it before publication.

> public Object markArrayInitialized(Object array) { /*mem-fence?*/ return array; }

It can't really be enforced, but it makes a clear target for best practices.

I find it very useful, when thinking about safe object allocation, to
distinguish between larval and public stages.  The mAI function makes
it very explicit where the stage change happens.  And it could map
directly into the C2 IR, which represents these stages internally.

— John


More information about the jdk9-dev mailing list