< prev index next > src/java.base/share/classes/java/lang/foreign/Linker.java
Print this page
import jdk.internal.foreign.abi.AbstractLinker;
import jdk.internal.foreign.abi.LinkerOptions;
import jdk.internal.foreign.abi.CapturableState;
import jdk.internal.foreign.abi.SharedUtils;
- import jdk.internal.javac.PreviewFeature;
import jdk.internal.reflect.CallerSensitive;
- import jdk.internal.reflect.Reflection;
import java.lang.invoke.MethodHandle;
import java.nio.ByteOrder;
import java.util.Objects;
- import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.internal.foreign.abi.AbstractLinker;
import jdk.internal.foreign.abi.LinkerOptions;
import jdk.internal.foreign.abi.CapturableState;
import jdk.internal.foreign.abi.SharedUtils;
import jdk.internal.reflect.CallerSensitive;
import java.lang.invoke.MethodHandle;
import java.nio.ByteOrder;
+ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
* <li>A linker allows Java code to link against foreign functions, via
* {@linkplain #downcallHandle(MemorySegment, FunctionDescriptor, Option...) downcall method handles}; and</li>
* <li>A linker allows foreign functions to call Java method handles,
* via the generation of {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, Arena, Option...) upcall stubs}.</li>
* </ul>
+ * A linker provides a way to look up the <em>canonical layouts</em> associated with the data types used by the ABI.
+ * For example, a linker implementing the C ABI might choose to provide a canonical layout for the C {@code size_t}
+ * type. On 64-bit platforms, this canonical layout might be equal to {@link ValueLayout#JAVA_LONG}. The canonical
+ * layouts supported by a linker are exposed via the {@link #canonicalLayouts()} method, which returns a map from
+ * type names to canonical layouts.
+ * <p>
* In addition, a linker provides a way to look up foreign functions in libraries that conform to the ABI. Each linker
* chooses a set of libraries that are commonly used on the OS and processor combination associated with the ABI.
* For example, a linker for Linux/x64 might choose two libraries: {@code libc} and {@code libm}. The functions in these
* libraries are exposed via a {@linkplain #defaultLookup() symbol lookup}.
*
* {@link #downcallHandle(MemorySegment, FunctionDescriptor, Option...)} method.
* The obtained downcall method handle is then invoked as follows:
*
* {@snippet lang = java:
* try (Arena arena = Arena.ofConfined()) {
! * MemorySegment str = arena.allocateUtf8String("Hello");
* long len = (long) strlen.invokeExact(str); // 5
* }
! * }
* <h3 id="describing-c-sigs">Describing C signatures</h3>
*
* When interacting with the native linker, clients must provide a platform-dependent description of the signature
* of the C function they wish to link against. This description, a {@link FunctionDescriptor function descriptor},
* defines the layouts associated with the parameter types and return type (if any) of the C function.
* <p>
* Scalar C types such as {@code bool}, {@code int} are modelled as {@linkplain ValueLayout value layouts}
! * of a suitable carrier. The mapping between a scalar type and its corresponding layout is dependent on the ABI
! * implemented by the native linker. For instance, the C type {@code long} maps to the layout constant
- * {@link ValueLayout#JAVA_LONG} on Linux/x64, but maps to the layout constant {@link ValueLayout#JAVA_INT} on
- * Windows/x64. Similarly, the C type {@code size_t} maps to the layout constant {@link ValueLayout#JAVA_LONG}
- * on 64-bit platforms, but maps to the layout constant {@link ValueLayout#JAVA_INT} on 32-bit platforms.
* <p>
* Composite types are modelled as {@linkplain GroupLayout group layouts}. More specifically, a C {@code struct} type
* maps to a {@linkplain StructLayout struct layout}, whereas a C {@code union} type maps to a {@link UnionLayout union
* layout}. When defining a struct or union layout, clients must pay attention to the size and alignment constraint
* of the corresponding composite type definition in C. For instance, padding between two struct fields
* {@link #downcallHandle(MemorySegment, FunctionDescriptor, Option...)} method.
* The obtained downcall method handle is then invoked as follows:
*
* {@snippet lang = java:
* try (Arena arena = Arena.ofConfined()) {
! * MemorySegment str = arena.allocateFrom("Hello");
* long len = (long) strlen.invokeExact(str); // 5
* }
! *}
* <h3 id="describing-c-sigs">Describing C signatures</h3>
*
* When interacting with the native linker, clients must provide a platform-dependent description of the signature
* of the C function they wish to link against. This description, a {@link FunctionDescriptor function descriptor},
* defines the layouts associated with the parameter types and return type (if any) of the C function.
* <p>
* Scalar C types such as {@code bool}, {@code int} are modelled as {@linkplain ValueLayout value layouts}
! * of a suitable carrier. The {@linkplain #canonicalLayouts() mapping} between a scalar type and its corresponding
! * canonical layout is dependent on the ABI implemented by the native linker (see below).
* <p>
* Composite types are modelled as {@linkplain GroupLayout group layouts}. More specifically, a C {@code struct} type
* maps to a {@linkplain StructLayout struct layout}, whereas a C {@code union} type maps to a {@link UnionLayout union
* layout}. When defining a struct or union layout, clients must pay attention to the size and alignment constraint
* of the corresponding composite type definition in C. For instance, padding between two struct fields
* {@linkplain AddressLayout address layouts}. When the spatial bounds of the pointer type are known statically,
* the address layout can be associated with a {@linkplain AddressLayout#targetLayout() target layout}. For instance,
* a pointer that is known to point to a C {@code int[2]} array can be modelled as an address layout whose
* target layout is a sequence layout whose element count is 2, and whose element type is {@link ValueLayout#JAVA_INT}.
* <p>
! * The following table shows some examples of how C types are modelled in Linux/x64:
*
* <blockquote><table class="plain">
* <caption style="display:none">Mapping C types</caption>
* <thead>
* <tr>
* {@linkplain AddressLayout address layouts}. When the spatial bounds of the pointer type are known statically,
* the address layout can be associated with a {@linkplain AddressLayout#targetLayout() target layout}. For instance,
* a pointer that is known to point to a C {@code int[2]} array can be modelled as an address layout whose
* target layout is a sequence layout whose element count is 2, and whose element type is {@link ValueLayout#JAVA_INT}.
* <p>
! * All native linker implementations are guaranteed to provide canonical layouts for the following set of types:
+ * <ul>
+ * <li>{@code bool}</li>
+ * <li>{@code char}</li>
+ * <li>{@code short}</li>
+ * <li>{@code int}</li>
+ * <li>{@code long}</li>
+ * <li>{@code long long}</li>
+ * <li>{@code float}</li>
+ * <li>{@code double}</li>
+ * <li>{@code size_t}</li>
+ * <li>{@code wchar_t}</li>
+ * <li>{@code void*}</li>
+ * </ul>
+ * As noted above, the specific canonical layout associated with each type can vary, depending on the data model
+ * supported by a given ABI. For instance, the C type {@code long} maps to the layout constant {@link ValueLayout#JAVA_LONG}
+ * on Linux/x64, but maps to the layout constant {@link ValueLayout#JAVA_INT} on Windows/x64. Similarly, the C type
+ * {@code size_t} maps to the layout constant {@link ValueLayout#JAVA_LONG} on 64-bit platforms, but maps to the layout
+ * constant {@link ValueLayout#JAVA_INT} on 32-bit platforms.
+ * <p>
+ * A native linker typically does not provide canonical layouts for C's unsigned integral types. Instead, they are
+ * modelled using the canonical layouts associated with their corresponding signed integral types. For instance,
+ * the C type {@code unsigned long} maps to the layout constant {@link ValueLayout#JAVA_LONG} on Linux/x64, but maps to
+ * the layout constant {@link ValueLayout#JAVA_INT} on Windows/x64.
+ * <p>
+ * The following table shows some examples of how C types are modelled in Linux/x64 (all the examples provided
+ * here will assume these platform-dependent mappings):
*
* <blockquote><table class="plain">
* <caption style="display:none">Mapping C types</caption>
* <thead>
* <tr>
* </thead>
* <tbody>
* <tr><th scope="row" style="font-weight:normal">{@code bool}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_BOOLEAN}</td>
* <td style="text-align:center;">{@code boolean}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code char}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_BYTE}</td>
* <td style="text-align:center;">{@code byte}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code short}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_SHORT}</td>
* <td style="text-align:center;">{@code short}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code int}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_INT}</td>
* <td style="text-align:center;">{@code int}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code long}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_LONG}</td>
* <td style="text-align:center;">{@code long}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code long long}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_LONG}</td>
* <td style="text-align:center;">{@code long}</td>
* <tr><th scope="row" style="font-weight:normal">{@code float}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_FLOAT}</td>
* <td style="text-align:center;">{@code float}</td>
* </thead>
* <tbody>
* <tr><th scope="row" style="font-weight:normal">{@code bool}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_BOOLEAN}</td>
* <td style="text-align:center;">{@code boolean}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code char} <br> {@code unsigned char}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_BYTE}</td>
* <td style="text-align:center;">{@code byte}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code short} <br> {@code unsigned short}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_SHORT}</td>
* <td style="text-align:center;">{@code short}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code int} <br> {@code unsigned int}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_INT}</td>
* <td style="text-align:center;">{@code int}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code long} <br> {@code unsigned long}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_LONG}</td>
* <td style="text-align:center;">{@code long}</td>
! * <tr><th scope="row" style="font-weight:normal">{@code long long} <br> {@code unsigned long long}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_LONG}</td>
* <td style="text-align:center;">{@code long}</td>
* <tr><th scope="row" style="font-weight:normal">{@code float}</th>
* <td style="text-align:center;">{@link ValueLayout#JAVA_FLOAT}</td>
* <td style="text-align:center;">{@code float}</td>
* </table></blockquote>
* <p>
* All native linker implementations operate on a subset of memory layouts. More formally, a layout {@code L}
* is supported by a native linker {@code NL} if:
* <ul>
! * <li>{@code L} is a value layout {@code V} and {@code V.withoutName()} is {@linkplain MemoryLayout#equals(Object) equal}
- * to one of the following layout constants:
- * <ul>
- * <li>{@link ValueLayout#JAVA_BOOLEAN}</li>
- * <li>{@link ValueLayout#JAVA_BYTE}</li>
- * <li>{@link ValueLayout#JAVA_CHAR}</li>
- * <li>{@link ValueLayout#JAVA_SHORT}</li>
- * <li>{@link ValueLayout#JAVA_INT}</li>
- * <li>{@link ValueLayout#JAVA_LONG}</li>
- * <li>{@link ValueLayout#JAVA_FLOAT}</li>
- * <li>{@link ValueLayout#JAVA_DOUBLE}</li>
- * </ul></li>
- * <li>{@code L} is an address layout {@code A} and {@code A.withoutTargetLayout().withoutName()} is
- * {@linkplain MemoryLayout#equals(Object) equal} to {@link ValueLayout#ADDRESS}</li>
* <li>{@code L} is a sequence layout {@code S} and all the following conditions hold:
* <ol>
* <li>the alignment constraint of {@code S} is set to its <a href="MemoryLayout.html#layout-align">natural alignment</a>, and</li>
* <li>{@code S.elementLayout()} is a layout supported by {@code NL}.</li>
* </ol>
* </table></blockquote>
* <p>
* All native linker implementations operate on a subset of memory layouts. More formally, a layout {@code L}
* is supported by a native linker {@code NL} if:
* <ul>
! * <li>{@code L} is a value layout {@code V} and {@code V.withoutName()} is a canonical layout</li>
* <li>{@code L} is a sequence layout {@code S} and all the following conditions hold:
* <ol>
* <li>the alignment constraint of {@code S} is set to its <a href="MemoryLayout.html#layout-align">natural alignment</a>, and</li>
* <li>{@code S.elementLayout()} is a layout supported by {@code NL}.</li>
* </ol>
* pointer, to the {@code qsort} downcall handle, as follows:
*
* {@snippet lang = java:
* try (Arena arena = Arena.ofConfined()) {
* MemorySegment comparFunc = linker.upcallStub(comparHandle, comparDesc, arena);
! * MemorySegment array = arena.allocateArray(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7);
* qsort.invokeExact(array, 10L, 4L, comparFunc);
* int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
* }
* }
*
* pointer, to the {@code qsort} downcall handle, as follows:
*
* {@snippet lang = java:
* try (Arena arena = Arena.ofConfined()) {
* MemorySegment comparFunc = linker.upcallStub(comparHandle, comparDesc, arena);
! * MemorySegment array = arena.allocateFrom(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7);
* qsort.invokeExact(array, 10L, 4L, comparFunc);
* int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
* }
* }
*
* specifically, the obtained segment has the desired size, can only be accessed by a single thread (the thread which created
* the confined arena), and its lifetime is tied to the surrounding <em>try-with-resources</em> block.
*
* <h3 id="variadic-funcs">Variadic functions</h3>
*
! * Variadic functions are C functions which can accept a variable number and type of arguments. They are declared:
! * <ol>
! * <li>With a trailing ellipsis ({@code ...}) at the end of the formal parameter list, such as: {@code void foo(int x, ...);}</li>
! * <li>With an empty formal parameter list, called a prototype-less function, such as: {@code void foo();}</li>
! * </ol>
- * The arguments passed in place of the ellipsis, or the arguments passed to a prototype-less function are called
- * <em>variadic arguments</em>. Variadic functions are, essentially, templates that can be <em>specialized</em> into multiple
- * non-variadic functions by replacing the {@code ...} or empty formal parameter list with a list of <em>variadic parameters</em>
- * of a fixed number and type.
* <p>
* It should be noted that values passed as variadic arguments undergo default argument promotion in C. For instance, the
* following argument promotions are applied:
* <ul>
* <li>{@code _Bool} -> {@code unsigned int}</li>
* specifically, the obtained segment has the desired size, can only be accessed by a single thread (the thread which created
* the confined arena), and its lifetime is tied to the surrounding <em>try-with-resources</em> block.
*
* <h3 id="variadic-funcs">Variadic functions</h3>
*
! * Variadic functions are C functions which can accept a variable number and type of arguments. They are declared with a
! * trailing ellipsis ({@code ...}) at the end of the formal parameter list, such as: {@code void foo(int x, ...);}.
! * The arguments passed in place of the ellipsis are called <em>variadic arguments</em>. Variadic functions are,
! * essentially, templates that can be <em>specialized</em> into multiple non-variadic functions by replacing the
! * {@code ...} with a list of <em>variadic parameters</em> of a fixed number and type.
* <p>
* It should be noted that values passed as variadic arguments undergo default argument promotion in C. For instance, the
* following argument promotions are applied:
* <ul>
* <li>{@code _Bool} -> {@code unsigned int}</li>
* <li>{@code [signed] short} -> {@code [signed] int}</li>
* <li>{@code float} -> {@code double}</li>
* </ul>
* whereby the signed-ness of the source type corresponds to the signed-ness of the promoted type. The complete process
* of default argument promotion is described in the C specification. In effect these promotions place limits on the
! * specialized form of a variadic function, as the variadic parameters of the specialized form will always have a promoted
! * type.
* <p>
* The native linker only supports linking the specialized form of a variadic function. A variadic function in its specialized
* form can be linked using a function descriptor describing the specialized form. Additionally, the
* {@link Linker.Option#firstVariadicArg(int)} linker option must be provided to indicate the first variadic parameter in
* the parameter list. The corresponding argument layout (if any), and all following argument layouts in the specialized
! * function descriptor, are called <em>variadic argument layouts</em>. For a prototype-less function, the index passed to
- * {@link Linker.Option#firstVariadicArg(int)} should always be {@code 0}.
* <p>
! * The native linker will reject an attempt to link a specialized function descriptor with any variadic argument layouts
! * corresponding to a C type that would be subject to default argument promotion (as described above). Exactly which layouts
! * will be rejected is platform specific, but as an example: on Linux/x64 the layouts {@link ValueLayout#JAVA_BOOLEAN},
! * {@link ValueLayout#JAVA_BYTE}, {@link ValueLayout#JAVA_CHAR}, {@link ValueLayout#JAVA_SHORT}, and
! * {@link ValueLayout#JAVA_FLOAT} will be rejected.
* <p>
* A well-known variadic function is the {@code printf} function, defined in the C standard library:
*
* {@snippet lang = c:
* int printf(const char *format, ...);
* <li>{@code [signed] short} -> {@code [signed] int}</li>
* <li>{@code float} -> {@code double}</li>
* </ul>
* whereby the signed-ness of the source type corresponds to the signed-ness of the promoted type. The complete process
* of default argument promotion is described in the C specification. In effect these promotions place limits on the
! * types that can be used to replace the {@code ...}, as the variadic parameters of the specialized form of a variadic
! * function will always have a promoted type.
* <p>
* The native linker only supports linking the specialized form of a variadic function. A variadic function in its specialized
* form can be linked using a function descriptor describing the specialized form. Additionally, the
* {@link Linker.Option#firstVariadicArg(int)} linker option must be provided to indicate the first variadic parameter in
* the parameter list. The corresponding argument layout (if any), and all following argument layouts in the specialized
! * function descriptor, are called <em>variadic argument layouts</em>.
* <p>
! * The native linker does not automatically perform default argument promotions. However, since passing an argument of a
! * non-promoted type as a variadic argument is not supported in C, the native linker will reject an attempt to link a
! * specialized function descriptor with any variadic argument value layouts corresponding to a non-promoted C type.
! * Since the size of the C {@code int} type is platform-specific, exactly which layouts will be rejected is
! * platform-specific as well. As an example: on Linux/x64 the layouts corresponding to the C types {@code _Bool},
+ * {@code (unsigned) char}, {@code (unsigned) short}, and {@code float} (among others), will be rejected by the linker.
+ * The {@link #canonicalLayouts()} method can be used to find which layout corresponds to a particular C type.
* <p>
* A well-known variadic function is the {@code printf} function, defined in the C standard library:
*
* {@snippet lang = c:
* int printf(const char *format, ...);
*
* We can then call the specialized downcall handle as usual:
*
* {@snippet lang = java:
* try (Arena arena = Arena.ofConfined()) {
! * int res = (int)printf.invokeExact(arena.allocateUtf8String("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4"
- * }
* }
*
* <h2 id="safety">Safety considerations</h2>
*
* Creating a downcall method handle is intrinsically unsafe. A symbol in a foreign library does not, in general,
* contain enough signature information (e.g. arity and types of foreign function parameters). As a consequence,
*
* We can then call the specialized downcall handle as usual:
*
* {@snippet lang = java:
* try (Arena arena = Arena.ofConfined()) {
! * int res = (int)printf.invokeExact(arena.allocateFrom("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4"
* }
+ *}
*
* <h2 id="safety">Safety considerations</h2>
*
* Creating a downcall method handle is intrinsically unsafe. A symbol in a foreign library does not, in general,
* contain enough signature information (e.g. arity and types of foreign function parameters). As a consequence,
* and even JVM crashes, since an upcall is typically executed in the context of a downcall method handle invocation.
*
* @implSpec
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
*
! * @since 19
*/
- @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
public sealed interface Linker permits AbstractLinker {
/**
* {@return a linker for the ABI associated with the underlying native platform} The underlying native platform
* is the combination of OS and processor where the Java runtime is currently executing.
*
* @apiNote It is not currently possible to obtain a linker for a different combination of OS and processor.
* @implNote The libraries exposed by the {@linkplain #defaultLookup() default lookup} associated with the returned
* linker are the native libraries loaded in the process where the Java runtime is currently executing. For example,
* on Linux, these libraries typically include {@code libc}, {@code libm} and {@code libdl}.
- *
- * @throws UnsupportedOperationException if the underlying native platform is not supported.
*/
static Linker nativeLinker() {
return SharedUtils.getSystemLinker();
}
* and even JVM crashes, since an upcall is typically executed in the context of a downcall method handle invocation.
*
* @implSpec
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
*
! * @since 22
*/
public sealed interface Linker permits AbstractLinker {
/**
* {@return a linker for the ABI associated with the underlying native platform} The underlying native platform
* is the combination of OS and processor where the Java runtime is currently executing.
*
* @apiNote It is not currently possible to obtain a linker for a different combination of OS and processor.
+ * @implSpec A native linker implementation is guaranteed to provide canonical layouts for
+ * <a href="#describing-c-sigs">basic C types</a>.
* @implNote The libraries exposed by the {@linkplain #defaultLookup() default lookup} associated with the returned
* linker are the native libraries loaded in the process where the Java runtime is currently executing. For example,
* on Linux, these libraries typically include {@code libc}, {@code libm} and {@code libdl}.
*/
static Linker nativeLinker() {
return SharedUtils.getSystemLinker();
}
* a fresh scope that is always alive. Under normal conditions, the size of the returned segment is {@code 0}.
* However, if the function descriptor's return layout has a {@linkplain AddressLayout#targetLayout() target layout}
* {@code T}, then the size of the returned segment is set to {@code T.byteSize()}.
* <p>
* The returned method handle will throw an {@link IllegalArgumentException} if the {@link MemorySegment}
! * representing the target address of the foreign function is the {@link MemorySegment#NULL} address.
! * The returned method handle will additionally throw {@link NullPointerException} if any argument passed to it is {@code null}.
* <p>
* This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
* Restricted methods are unsafe, and, if used incorrectly, their use might crash
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
* a fresh scope that is always alive. Under normal conditions, the size of the returned segment is {@code 0}.
* However, if the function descriptor's return layout has a {@linkplain AddressLayout#targetLayout() target layout}
* {@code T}, then the size of the returned segment is set to {@code T.byteSize()}.
* <p>
* The returned method handle will throw an {@link IllegalArgumentException} if the {@link MemorySegment}
! * representing the target address of the foreign function is the {@link MemorySegment#NULL} address. If an argument
! * is a {@link MemorySegment},whose corresponding layout is an {@linkplain GroupLayout group layout}, the linker might attempt to access the contents of the segment. As such, one of the exceptions specified by the
+ * {@link MemorySegment#get(ValueLayout.OfByte, long)} or the
+ * {@link MemorySegment#copy(MemorySegment, long, MemorySegment, long, long)} methods may be thrown.
+ * The returned method handle will additionally throw {@link NullPointerException} if any argument
+ * passed to it is {@code null}.
* <p>
* This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
* Restricted methods are unsafe, and, if used incorrectly, their use might crash
* the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
* restricted methods, and use safe and supported functionalities, where possible.
* across all the OS and processor combinations.
* @return a symbol lookup for symbols in a set of commonly used libraries.
*/
SymbolLookup defaultLookup();
/**
* A linker option is used to provide additional parameters to a linkage request.
! * @since 20
*/
- @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
sealed interface Option
permits LinkerOptions.LinkerOptionImpl {
/**
* {@return a linker option used to denote the index indicating the start of the variadic arguments passed to the
* across all the OS and processor combinations.
* @return a symbol lookup for symbols in a set of commonly used libraries.
*/
SymbolLookup defaultLookup();
+ /**
+ * {@return an unmodifiable mapping between the names of data types used by the ABI implemented by this linker and their
+ * <em>canonical layouts</em>}
+ * <p>
+ * Each {@link Linker} is responsible for choosing the data types that are widely recognized as useful on the OS
+ * and processor combination supported by the {@link Linker}. Accordingly, the precise set of data type names
+ * and canonical layouts exposed by the linker is unspecified; it varies from one {@link Linker} to another.
+ * @implNote It is strongly recommended that the result of {@link #canonicalLayouts()} exposes a set of symbols that is stable over time.
+ * Clients of {@link #canonicalLayouts()} are likely to fail if a data type that was previously exposed by the linker
+ * is no longer exposed, or if its canonical layout is updated.
+ * <p>If an implementer provides {@link Linker} implementations for multiple OS and processor combinations, then it is strongly
+ * recommended that the result of {@link #canonicalLayouts()} exposes, as much as possible, a consistent set of symbols
+ * across all the OS and processor combinations.
+ */
+ Map<String, MemoryLayout> canonicalLayouts();
+
/**
* A linker option is used to provide additional parameters to a linkage request.
! * @since 22
*/
sealed interface Option
permits LinkerOptions.LinkerOptionImpl {
/**
* {@return a linker option used to denote the index indicating the start of the variadic arguments passed to the
* int errno = (int) errnoHandle.get(capturedState);
* // use errno
* }
* }
*
+ * @apiNote This linker option can not be combined with {@link #critical}.
+ *
* @param capturedState the names of the values to save.
* @throws IllegalArgumentException if at least one of the provided {@code capturedState} names
* is unsupported on the current platform.
* @see #captureStateLayout()
*/
static StructLayout captureStateLayout() {
return CapturableState.LAYOUT;
}
/**
! * {@return a linker option used to mark a foreign function as <em>trivial</em>}
* <p>
! * A trivial function is a function that has an extremely short running time
! * in all cases (similar to calling an empty function), and does not call back into Java (e.g. using an upcall stub).
* <p>
* Using this linker option is a hint which some implementations may use to apply
! * optimizations that are only valid for trivial functions.
* <p>
! * Using this linker option when linking non trivial functions is likely to have adverse effects,
* such as loss of performance, or JVM crashes.
*/
! static Option isTrivial() {
! return LinkerOptions.IsTrivial.INSTANCE;
}
}
}
static StructLayout captureStateLayout() {
return CapturableState.LAYOUT;
}
/**
! * {@return a linker option used to mark a foreign function as <em>critical</em>}
* <p>
! * A critical function is a function that has an extremely short running time in all cases
! * (similar to calling an empty function), and does not call back into Java (e.g. using an upcall stub).
* <p>
* Using this linker option is a hint which some implementations may use to apply
! * optimizations that are only valid for critical functions.
* <p>
! * Using this linker option when linking non-critical functions is likely to have adverse effects,
* such as loss of performance, or JVM crashes.
*/
! static Option critical() {
! return LinkerOptions.Critical.INSTANCE;
}
}
}
< prev index next >