Update to description of JEP 193: Enhanced Volatiles

Paul Sandoz paul.sandoz at oracle.com
Fri Oct 31 13:37:26 UTC 2014


Hi Remi,

Thanks, that's an interesting approach which has not previously occurred to me.

So this proposal combines lookup and access into one call. IIUC to do that effectively the dynamic call site needs to initially provide a "slow" MH that performs an access-control-check, and then updates the call site (once only) with a MH performing the faster check that assumes the field identifier is held constant (and if not barfs).

I find the use of the String a little raw, it does not uniquely identify a field, unless there is more information encoded, and is error prone when repeatedly declared. There is one less possible runtime exception for arity but that is counter balanced with one each for access control and constant-check per call-site. 

If we could introduce a more formal field identifier it would strengthen the proposal. So i think it worth keeping this idea around while seeing how we progress with handles and especially generic handles.


We could perform similar checks on VarHandle invocation too with a dynamic call site, if such integrity [1] is a concern. For non-public fields, the slow path checks that the lookup class has access to the receiver class before proceeding [2], although that would then differentiate from MH behaviour. It could even be configured as something optional, or even perhaps programatically "these are the set of classes i give access permission".

An obvious observation: existing Unsafe or Atomic*Update refs need to be guarded from leakage, so this pattern is not new or unexpected. When converting Unsafe usages to VarHandle it's quite simple to maintain that pattern. Further, it's possible have tooling that detect such leaks.

Paul.

[1] I am more concerned about integrity ("private" means private etc.) rather than security with a security manager.

[2] Can such checks be folded away?


On Oct 30, 2014, at 8:58 PM, Remi Forax <forax at univ-mlv.fr> wrote:

> 
> On 10/30/2014 04:53 PM, Paul Sandoz wrote:
>> On Oct 30, 2014, at 4:47 PM, Remi Forax <forax at univ-mlv.fr> wrote:
>> 
>>> On 10/30/2014 03:02 PM, Paul Sandoz wrote:
>>>> Hi,
>>>> 
>>>> I have, with the help of Brian, Doug and John, updated the description of JEP 193: Enhanced Volatiles to reflect our current thinking based on:
>>>> 
>>>> - the prototype implementation in valhalla;
>>>> - performance measurements of that implementation; and
>>>> - investigations related to signature polymorphic methods and invokedynamic.
>>>> 
>>>> Thanks,
>>>> Paul.
>>> I seems that the changes are not propagated to the JEP yet,
>>> but there are available throught the corresponding bug:
>>>  https://bugs.openjdk.java.net/browse/JDK-8046183
>>> 
>> Doh! thanks, i forgot to send the link out,
>> Paul,
> 
> Here is a kind of counter-proposal because I think that there is a far simpler and more secure API.
> 
> I think that instead of having to first instantiate an object (VarHandle) and then call a method on it,
> this can be done in one method.
> 
> |public  class  Safe  {
>    @Intrinsic
>     public  staticObject  get(Object receiver, String fieldName) { }|
> ||     @Intrinsic
>     public  staticObject  getRelaxed(Object receiver, String fieldName) { }|
>    ||||@Intrinsic||
>    ||||public  staticObject  getAcquire(Object receiver, String fieldName) { }|||
> ||||||     @Intrinsic|||
>    ||||public  staticObject  getRelaxed(Object receiver, String fieldName) { }|||
> |||||     @Intrinsic||||
>    ||||public  staticObject  |||||||getSequential|(Object receiver, String fieldName) { }||
> |
> ||||||     @Intrinsic|||||
>    |||public  static  void  set(|||||||Object receiver, String fieldName|||, Object value) { }|
>    // and all other related variations
>      ...        }|
> 
> and this is how to use it:
> 
> class  Foo  {
> 
> |    int i;
> 
>    public void acquire() {
>     |||boolean  r=  (boolean)Safe.compareAndSet(this, "i",  0,  1);
>     ...
> |    }
> }|
> 
> 
> At compile time, the compiler checks that a method Safe.compareAndSet with compatible parameter types exists
> but instead of generating an invokestatic, it generates an invokedynamic which uses the signature of the actual callsite.
> Using the actual types in the signature allows to avoid unnecessary boxing while
> keeping the typechecking rules simples (they are not changed !) as explained in the current draft of JEP 193.
> 
> This API doesn't use any object to represent a field but uses a String as field name, you may think that
> 1) this mean that the field will be queried each time:
>    It doesn't has to. invokedynamic allow to install a dynamic check that will test that the string doesn't change
>    from one call to another. This check will be removed by the JIT because the string never change
>    (if the string change, the best is to throw a runtime exception like IllegalArgumentException explaining
>     that the field name must be a constant).
> 2) that using a String is not typesafe. Having a typesafe API is hard here, because the type of a field
>    is not something you can get at compile time, there is no field reference syntax in Java (no Foo::i),
>    so a String seems to be a good practical choice.
> 
> And this API has a true real advantage compared to the VarHandle API, this API is inherently more secure.
> A VarHandle or any object representing a field will have some special security credential because it can access
> to a field without having to check at runtime if the field is visible from where the call is done (for performance reason).
> From my own experience, it's too easy to make this kind of object too visible introduced a security hole without
> even doing something hard.
> By not reifying the access to a field as an object, the API is more secure with the restriction
> that a method can only access to the field of the class that contains the call to the API.
> 
> In term of implementation, the compiler will generate this bytecode for the class Foo:
> 
> ||class  Foo  {
> 
> |    int i;
> 
>    public void acquire() {
>     invokedynamic "compareAndSet" (Foo;String;II)Z
>       BSM =||java.lang.invoke.SafeMetaProtocol|||.bootstrap(Lookup;String;MethodType;MethodHandle)
>       ARG = MH(||||||Safe.compareAndSet(||Object;String;Object;Object;)
>     istore 0||||
>     ...
> |    }
> }|
> 
> and from the JLS perspective, the compiler will recognize that the method inside Safe
> are special because there are annotated by an annotation that has a meta-annotation
> named BootstrapMethod that specifies the bootstrap method that should be used
> when emitting the invokedynamic call.
> 
> ||||
> 
> @BootstrapMethod(type=java.lang.invoke.SafeMetaProtocol.class, name="bootstrap")
> @interface Intrinsic {
>  // empty
> }
> 
> cheers,
> Rémi
> 



More information about the valhalla-dev mailing list