Update to description of JEP 193: Enhanced Volatiles

Remi Forax forax at univ-mlv.fr
Fri Oct 31 15:59:57 UTC 2014


On 10/31/2014 02:57 PM, MacGregor, Duncan (GE Energy Management) wrote:
> I like the overall idea but also think the string feels wrong, it suggests
> that both the class of the object and the field name could be dynamic and
> might change with every invocation, but I really doubt we¹d want that.

A previous iteration of the API (in my head) was using a class named 
FieldMirror like this:
public class Safe {
   @Instrinsic
   public static <T, V> V get(T receiver, FieldMirror<T, V> fieldMirror) { }
   ...
}

public class FieldMirror<T, V> {
   public FieldMirror(Class<T> declaringClass, String fieldName, 
Class<V> fieldType) { ... }
}

class Foo {
   private static final FieldMirror<Foo, Integer> Foo_i = new 
FieldMirror<>(Foo.class, "i", int.class);
   int i;

   public int get() {
      return (int)Safe.get(this, Foo_i);
   }
}

In that case, the creation of the FieldMirror requires to check if the 
field exist and we need a supplementary check in the slow MH as Paul 
called it, to verify that
the field mirror reference a visible field from the callsite. While 
sending a String is ugly, it avoids this double check.
Duncan, as you can see, it also suggests that the field mirror taken as 
argument of Safe.get() can be dynamic too,
so I don't see this API as an improvement, not compared to

class Foo {
   private static final String Foo_i = "i";
   int i;

   public int get() {
      return (int)Safe.get(this, Foo_i);
   }
}

As I said, apart if we have a compiler representation of a field 
reference, something like Foo::i,
I think I prefer to stick with Strings.

> [...]
>
> Regards, Duncan.

Rémi

>
> On 31/10/2014 13:37, "Paul Sandoz" <paul.sandoz at oracle.com> wrote:
>
>> 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;MethodTyp
>>> e;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