[foreign-abi] minimizing the surface of restricted native access
Jorn Vernee
jorn.vernee at oracle.com
Fri Nov 29 12:27:33 UTC 2019
Hi Ty,
Response inline...
On 29/11/2019 12:21, Ty Young wrote:
>
>
> On 11/29/19 3:07 AM, Maurizio Cimadamore wrote:
>> Hi Ty,
>> without entering in the specifics of your example - let's say you
>> know that getpid() is at address 42 (of course the address will be
>> much bigger, and even be a 'negative' Java long in reality).
>>
>> With the proposed model, you would be able to do:
>>
>> MemoryAddress pid = MemoryAddress.ofLong(42);
>>
>> And then you would be able to obtain a MethodHandle out of that,
>> using the SystemABI:
>>
>> MethodHandle handle = SystemABI.getInstance().downcallHandle(pid,
>> MethodType.methodType(int.class), FunctionDescriptor.of(C_INT));
>>
>> Then you can call the handle, normally.
>>
>> The only "unsafe" operation there is here, is the call to SystemABI
>> to obtain the MethodHandle. This is a place where the API has to
>> trust the developer because:
>>
>> - the entry point address could be invalid
>> - the function descriptor could be invalid leading to wrong calling
>> sequence
>>
>> In all these cases the results of calling an ill-formed handle would
>> be unpredictable (and there's no way to make this API safe - C
>> libraries w/o debugging info have zero info about function
>> signatures, so there's no way to check things - which leaves us in
>> the best effort-land **) - some of these situations can also arise
>> with JNI if the signature of the native method and the underlying C
>> header/impl are out of sync.
>>
>> But the memory access API (in its ABI-ready incarnation) should give
>> you a way to at least construct a pointer to the desired function.
>
>
> Thanks for the clarification.
>
>
> Are there any plans to make jdk.internal.foreign a default export?
> Currently it's one of the seemingly very few "internal" modules that
> aren't exported and I'll have to recompile from source with it
> exported in order to use it.
None of the packages with 'internal' in the name will be exported, since
they are not part of the public API, but an implementation detail. This
naming pattern is followed in many places in the JDK (e.g. java.base has
a bunch of these packages [1], which are not exported by default [2]).
Just like reflectively changing 'private' fields of a class is
ill-advised, because you can end up going around invariant
checks/assumptions and break the functioning of the class, you can break
invariants by directly accessing an implementation detail in an internal
package. So, no, this package will not be exported by default (just like
we don't make all our fields 'public'). This is also important for
keeping the option open of changing the implementation, which is much
harder if users outside of the JDK depend on that implementation.
Would you wish to access an internal package any ways, you would need to
provide an additional command line flag (--add-exports ...) to break the
encapsulation (similar to setAccessible(true) for hacking into a private
field). By providing the command line flag you explicitly except the
risk of breaking the VM, and the risk that the code you depend on can
change it's behavior or shape at any time, or becomes inaccessible
altogether. i.e. it's similar to removing a "warranty void if removed"
sticker found on some consumer electronics.
Of course, if you're making a library that depends on internal APIs, the
users of your library must also explicitly opt into using these
implementation details (through your library), and thus also explicitly
accept the risks tied to the use of internal code. While you may be
comfortable with removing the 'sticker', your clients might not be, so
they again have to opt in.
Jorn
[1] :
https://github.com/openjdk/jdk/tree/master/src/java.base/share/classes/jdk/internal
[2] :
https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/module-info.java
>>
>> Maurizio
>>
>> (**) The VM already has a nice diagnostic option called "-Xcheck:jni"
>> which performs a variety of checks; but, again, this is a best-effort
>> attempt and cannot detect all possible things that can go wrong (such
>> as mismatches between Java signatures and C signatures).
More information about the panama-dev
mailing list