Interface Linker
Foreign functions typically reside in libraries that can be loaded on demand. Each library conforms to a specific ABI (Application Binary Interface). An ABI is a set of calling conventions and data types associated with the compiler, OS, and processor where the library was built. For example, a C compiler on Linux/x64 usually builds libraries that conform to the SystemV ABI.
A linker has detailed knowledge of the calling conventions and data types used by a specific ABI. For any library that conforms to that ABI, the linker can mediate between Java code running in the JVM and foreign functions in the library. In particular:
- A linker allows Java code to link against foreign functions, via downcall method handlesRESTRICTED; and
- A linker allows foreign functions to call Java method handles, via the generation of upcall stubsRESTRICTED.
size_t type. On 64-bit platforms,
 this canonical layout might be equal to ValueLayout.JAVA_LONG. The canonical
 layouts supported by a linker are exposed via the canonicalLayouts() method,
 which returns a map from type names to canonical layouts.
 
 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: libc and libm. The functions in
 these libraries are exposed via a symbol lookup.
 
Calling native functions
The native linker can be used to link against functions defined in C libraries (native functions). Suppose we wish to downcall from Java to thestrlen function defined in the standard C library:
 
size_t strlen(const char *s);
strlen is obtained, using the native
 linker, as follows:
 
Linker linker = Linker.nativeLinker();
MethodHandle strlen = linker.downcallHandle(
    linker.defaultLookup().findOrThrow("strlen"),
    FunctionDescriptor.of(JAVA_LONG, ADDRESS)
);
strlen native
 function. That address is then passed, along with a platform-dependent description
 of the signature of the function expressed as a FunctionDescriptor (more on
 that below) to the native linker's downcallHandle(MemorySegment, FunctionDescriptor, Option...)RESTRICTED
 method. The obtained downcall method handle is then invoked as follows:
 
 try (Arena arena = Arena.ofConfined()) {
     MemorySegment str = arena.allocateFrom("Hello");
     long len = (long) strlen.invokeExact(str);  // 5
 }
Describing C signatures
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, afunction descriptor, defines the layouts
 associated with the parameter types and return type (if any) of the C function.
 
 Scalar C types such as bool, int are modeled as
 value layouts of a suitable carrier. The
 mapping between a scalar type and its corresponding
 canonical layout is dependent on the ABI implemented by the native linker (see below).
 
 Composite types are modeled as group layouts. More
 specifically, a C struct type maps to a struct layout,
 whereas a C union type maps to a 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 must be modeled explicitly, by adding an adequately sized
 padding layout member to the resulting struct layout.
 
 Finally, pointer types such as int** and int(*)(size_t*, size_t*)
 are modeled as address layouts. When the spatial bounds of
 the pointer type are known statically, the address layout can be associated with a
 target layout. For instance, a pointer that
 is known to point to a C int[2] array can be modeled as an address layout
 whose target layout is a sequence layout whose element count is 2, and whose
 element type is ValueLayout.JAVA_INT.
 
All native linker implementations are guaranteed to provide canonical layouts for the following set of types:
- bool
- char
- short
- int
- long
- long long
- float
- double
- size_t
- wchar_t
- void*
long maps to the layout constant ValueLayout.JAVA_LONG on Linux/x64,
 but maps to the layout constant ValueLayout.JAVA_INT on Windows/x64.
 Similarly, the C type size_t maps to the layout constant
 ValueLayout.JAVA_LONG on 64-bit platforms, but maps to the layout constant
 ValueLayout.JAVA_INT on 32-bit platforms.
 
 A native linker typically does not provide canonical layouts for C's unsigned integral
 types. Instead, they are modeled using the canonical layouts associated with their
 corresponding signed integral types. For instance, the C type unsigned long
 maps to the layout constant ValueLayout.JAVA_LONG on Linux/x64, but maps to
 the layout constant ValueLayout.JAVA_INT on Windows/x64.
 
The following table shows some examples of how C types are modeled in Linux/x64 according to the "System V Application Binary Interface" (all the examples provided here will assume these platform-dependent mappings):
C type Layout Java type boolValueLayout.JAVA_BOOLEANbooleanchar
unsigned charValueLayout.JAVA_BYTEbyteshort
unsigned shortValueLayout.JAVA_SHORTshortint
unsigned intValueLayout.JAVA_INTintlong
unsigned longValueLayout.JAVA_LONGlonglong long
unsigned long longValueLayout.JAVA_LONGlongfloatValueLayout.JAVA_FLOATfloatdoubleValueLayout.JAVA_DOUBLEdoublesize_tValueLayout.JAVA_LONGlongchar*,int**,struct Point*ValueLayout.ADDRESSMemorySegmentint (*ptr)[10]ValueLayout.ADDRESS.withTargetLayout( MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT) );MemorySegmentstruct Point { int x; long y; };MemoryLayout.structLayout( ValueLayout.JAVA_INT.withName("x"), MemoryLayout.paddingLayout(4), ValueLayout.JAVA_LONG.withName("y") );MemorySegmentunion Choice { float a; int b; }MemoryLayout.unionLayout( ValueLayout.JAVA_FLOAT.withName("a"), ValueLayout.JAVA_INT.withName("b") );MemorySegment
A native linker only supports function descriptors whose argument/return layouts are well-formed layouts. More formally, a layout `L` is well-formed if:
- Lis a value layout and- Lis derived from a canonical layout- Csuch that- L.byteAlignment() <= C.byteAlignment()
- Lis a sequence layout- Sand all the following conditions hold:- L.byteAlignment()is equal to the sequence layout's natural alignment , and
- S.elementLayout()is a well-formed layout.
 
- Lis a group layout- Gand all the following conditions hold:- G.byteAlignment()is equal to the group layout's natural alignment
- G.byteSize()is a multiple of- G.byteAlignment()
- Each member layout in G.memberLayouts()is either a padding layout or a well-formed layout
- Each non-padding member layout EinG.memberLayouts()follows an optional padding member layout, whose size is the minimum size required to alignE
- Gcontains an optional trailing padding member layout, whose size is the minimum size that satisfies (2)
 
A function descriptor is well-formed if its argument and return layouts are well-formed and are not sequence layouts. A native linker is guaranteed to reject function descriptors that are not well-formed. However, a native linker can still reject well-formed function descriptors, according to platform-specific rules. For example, some native linkers may reject packed struct layouts -- struct layouts whose member layouts feature relaxed alignment constraints, to avoid the insertion of additional padding.
Function pointers
Sometimes, it is useful to pass Java code as a function pointer to some native function; this is achieved by using an upcall stubRESTRICTED. To demonstrate this, let's consider the following function from the C standard library:void qsort(void *base, size_t nmemb, size_t size,
           int (*compar)(const void *, const void *));
qsort function can be used to sort the contents of an array, using a
 custom comparator function which is passed as a function pointer
 (the compar parameter). To be able to call the qsort function from
 Java, we must first create a downcall method handle for it, as follows:
 
Linker linker = Linker.nativeLinker();
MethodHandle qsort = linker.downcallHandle(
    linker.defaultLookup().findOrThrow("qsort"),
        FunctionDescriptor.ofVoid(ADDRESS, JAVA_LONG, JAVA_LONG, ADDRESS)
);
ValueLayout.JAVA_LONG to map the C type size_t type,
 and ValueLayout.ADDRESS for both the first pointer parameter (the array
 pointer) and the last parameter (the function pointer).
 
 To invoke the qsort downcall handle obtained above, we need a function pointer
 to be passed as the last parameter. That is, we need to create a function pointer out
 of an existing method handle. First, let's write a Java method that can compare two
 int elements passed as pointers (i.e. as memory segments):
 
class Qsort {
    static int qsortCompare(MemorySegment elem1, MemorySegment elem2) {
        return Integer.compare(elem1.get(JAVA_INT, 0), elem2.get(JAVA_INT, 0));
    }
}
FunctionDescriptor comparDesc = FunctionDescriptor.of(JAVA_INT,
                                                      ADDRESS.withTargetLayout(JAVA_INT),
                                                      ADDRESS.withTargetLayout(JAVA_INT));
MethodHandle comparHandle = MethodHandles.lookup()
                                         .findStatic(Qsort.class, "qsortCompare",
                                                     comparDesc.toMethodType());
int[] array, we can specify ValueLayout.JAVA_INT as the target
 layout for the address layouts of both parameters. This will allow the comparator
 method to access the contents of the array elements to be compared. We then
 turn that function descriptor into
 a suitable method type which we then use to
 look up the comparator method handle. We can now create an upcall stub that points to
 that method, and pass it, as a function pointer, to the qsort downcall handle,
 as follows:
 
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 ]
}
qsort method handle along with the comparator
 function we obtained from the native linker. After the invocation, the contents
 of the off-heap array will be sorted according to our comparator function, written in
 Java. We then extract a new Java array from the segment, which contains the sorted
 elements.
 Functions returning pointers
When interacting with native functions, it is common for those functions to allocate a region of memory and return a pointer to that region. Let's consider the following function from the C standard library:void *malloc(size_t size);
malloc function allocates a region of memory with the given size,
 and returns a pointer to that region of memory, which is later deallocated using
 another function from the C standard library:
 
void free(void *ptr);
free function takes a pointer to a region of memory and deallocates that
 region. In this section we will show how to interact with these native functions,
 with the aim of providing a safe allocation API (the approach outlined below
 can of course be generalized to allocation functions other than malloc and
 free).
 
 First, we need to create the downcall method handles for malloc and
 free, as follows:
 
Linker linker = Linker.nativeLinker();
MethodHandle malloc = linker.downcallHandle(
    linker.defaultLookup().findOrThrow("malloc"),
    FunctionDescriptor.of(ADDRESS, JAVA_LONG)
);
MethodHandle free = linker.downcallHandle(
    linker.defaultLookup().findOrThrow("free"),
    FunctionDescriptor.ofVoid(ADDRESS)
);
malloc) is invoked using
 a downcall method handle, the Java runtime has no insight into the size or the
 lifetime of the returned pointer. Consider the following code:
 
MemorySegment segment = (MemorySegment)malloc.invokeExact(100);
malloc downcall method handle is
 zero. Moreover, the scope of the
 returned segment is the global scope. To provide safe access to the segment, we must,
 unsafely, resize the segment to the desired size (100, in this case). It might also
 be desirable to attach the segment to some existing arena, so that
 the lifetime of the region of memory backing the segment can be managed automatically,
 as for any other native segment created directly from Java code. Both of these
 operations are accomplished using the restricted method
 MemorySegment.reinterpret(long, Arena, Consumer)RESTRICTED, as follows:
 
MemorySegment allocateMemory(long byteSize, Arena arena) throws Throwable {
    MemorySegment segment = (MemorySegment) malloc.invokeExact(byteSize); // size = 0, scope = always alive
    return segment.reinterpret(byteSize, arena, s -> {
        try {
            free.invokeExact(s);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    });  // size = byteSize, scope = arena.scope()
}
allocateMemory method defined above accepts two parameters: a size and an
 arena. The method calls the malloc downcall method handle, and unsafely
 reinterprets the returned segment, by giving it a new size (the size passed to the
 allocateMemory method) and a new scope (the scope of the provided arena).
 The method also specifies a cleanup action to be executed when the provided
 arena is closed. Unsurprisingly, the cleanup action passes the segment to the
 free downcall method handle, to deallocate the underlying region of memory.
 We can use the allocateMemory method as follows:
 
try (Arena arena = Arena.ofConfined()) {
    MemorySegment segment = allocateMemory(100, arena);
} // 'free' called here
allocateMemory acts as any other segment
 managed by the confined arena. More specifically, the obtained segment has the desired
 size, can only be accessed by a single thread (the thread that created the confined
 arena), and its lifetime is tied to the surrounding try-with-resources block.
 Variadic functions
Variadic functions are C functions that can accept a variable number and type of arguments. They are declared with a trailing ellipsis (...) at the end of the
 formal parameter list, such as: void foo(int x, ...);
 The arguments passed in place of the ellipsis are called variadic arguments.
 Variadic functions are, essentially, templates that can be specialized into
 multiple non-variadic functions by replacing the ... with a list of
 variadic parameters of a fixed number and type.
 It should be noted that values passed as variadic arguments undergo default argument promotion in C. For instance, the following argument promotions are applied:
- _Bool->- unsigned int
- [signed] char->- [signed] int
- [signed] short->- [signed] int
- float->- double
..., as the variadic parameters of the specialized form
 of a variadic function will always have a promoted type.
 
 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 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
 variadic argument layouts.
 
 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 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 _Bool,
 (unsigned) char, (unsigned) short, and float (among others),
 will be rejected by the linker. The canonicalLayouts() method can be used to
 find which layout corresponds to a particular C type.
 
 A well-known variadic function is the printf function, defined in the
 C standard library:
 
int printf(const char *format, ...);
printf("%d plus %d equals %d", 2, 2, 4);
(char*, int, int, int) as the format string accepts three integer parameters.
 We then need to use a linker option
 to specify the position of the first variadic layout in the provided function
 descriptor (starting from 0). In this case, since the first parameter is the format
 string (a non-variadic argument), the first variadic index needs to be set to 1, as
 follows:
 
Linker linker = Linker.nativeLinker();
MethodHandle printf = linker.downcallHandle(
    linker.defaultLookup().findOrThrow("printf"),
        FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT),
        Linker.Option.firstVariadicArg(1) // first int is variadic
);
 try (Arena arena = Arena.ofConfined()) {
     //prints "2 plus 2 equals 4"
     int res = (int)printf.invokeExact(arena.allocateFrom("%d plus %d equals %d"), 2, 2, 4);
 }
Safety considerations
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, the linker runtime cannot validate linkage requests. When a client interacts with a downcall method handle obtained through an invalid linkage request (e.g. by specifying a function descriptor featuring too many argument layouts), the result of such interaction is unspecified and can lead to JVM crashes.When an upcall stub is passed to a foreign function, a JVM crash might occur, if the foreign code casts the function pointer associated with the upcall stub to a type that is incompatible with the type of the upcall stub, and then attempts to invoke the function through the resulting function pointer. Moreover, if the method handle associated with an upcall stub returns a memory segment, clients must ensure that this address cannot become invalid after the upcall is completed. This can lead to unspecified behavior, and even JVM crashes, since an upcall is typically executed in the context of a downcall method handle invocation.
- Implementation Requirements:
- Implementations of this interface are immutable, thread-safe and value-based.
- Since:
- 22
- 
Nested Class SummaryNested ClassesModifier and TypeInterfaceDescriptionstatic interfaceA linker option is used to provide additional parameters to a linkage request.
- 
Method SummaryModifier and TypeMethodDescriptionReturns an unmodifiable mapping between the names of data types used by the ABI implemented by this linker and their canonical layouts.Returns a symbol lookup for symbols in a set of commonly used libraries.downcallHandle(FunctionDescriptor function, Linker.Option... options) Restricted.Creates a method handle that is used to call a foreign function with the given signature.downcallHandle(MemorySegment address, FunctionDescriptor function, Linker.Option... options) Restricted.Creates a method handle that is used to call a foreign function with the given signature and address.static LinkerReturns a linker for the ABI associated with the underlying native platform.upcallStub(MethodHandle target, FunctionDescriptor function, Arena arena, Linker.Option... options) Restricted.Creates an upcall stub which can be passed to other foreign functions as a function pointer, associated with the given arena.
- 
Method Details- 
nativeLinkerReturns 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. - API Note:
- It is not currently possible to obtain a linker for a different combination of OS and processor.
- Implementation Requirements:
- A native linker implementation is guaranteed to provide canonical layouts for basic C types.
- Implementation Note:
- The libraries exposed by the 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 libc,libmandlibdl.
- Returns:
- a linker for the ABI associated with the underlying native platform
 
- 
downcallHandleMethodHandle downcallHandle(MemorySegment address, FunctionDescriptor function, Linker.Option... options) downcallHandleis a restricted method of the Java platform.Restricted methods are unsafe, and, if used incorrectly, might crash the JVM or result in memory corruption.Creates a method handle that is used to call a foreign function with the given signature and address.Calling this method is equivalent to the following code: linker.downcallHandle(function, options).bindTo(address);- Parameters:
- address- the native memory segment whose base address is the address of the target foreign function
- function- the function descriptor of the target foreign function
- options- the linker options associated with this linkage request
- Returns:
- a downcall method handle
- Throws:
- IllegalArgumentException- if the provided function descriptor is not supported by this linker
- IllegalArgumentException- if- !address.isNative(), or if- address.equals(MemorySegment.NULL)
- IllegalArgumentException- if an invalid combination of linker options is given
- IllegalCallerException- if the caller is in a module that does not have native access enabled
- See Also:
 
- 
downcallHandledowncallHandleis a restricted method of the Java platform.Programs can only usedowncallHandlewhen access to restricted methods is enabled.Restricted methods are unsafe, and, if used incorrectly, might crash the JVM or result in memory corruption.Creates a method handle that is used to call a foreign function with the given signature.The Java method type associated with the returned method handle is derived from the argument and return layouts in the function descriptor, but features an additional leading parameter of type MemorySegment, from which the address of the target foreign function is derived. Moreover, if the function descriptor's return layout is a group layout, the resulting downcall method handle accepts an additional leading parameter of typeSegmentAllocator, which is used by the linker runtime to allocate the memory region associated with the struct returned by the downcall method handle.Upon invoking a downcall method handle, the linker provides the following guarantees for any argument Aof typeMemorySegmentwhose corresponding layout is an address layout:- A.scope().isAlive() == true. Otherwise, the invocation throws- IllegalStateException;
- The invocation occurs in a thread Tsuch thatA.isAccessibleBy(T) == true. Otherwise, the invocation throwsWrongThreadException; and
- Ais kept alive during the invocation. For instance, if- Ahas been obtained using a shared arena, any attempt to close the arena while the downcall method handle is still executing will result in an- IllegalStateException.
 Moreover, if the provided function descriptor's return layout is an address layout, invoking the returned method handle will return a native segment associated with the global scope. Under normal conditions, the size of the returned segment is 0. However, if the function descriptor's return layout has a target layoutT, then the size of the returned segment is set toT.byteSize().The returned method handle will throw an IllegalArgumentExceptionif theMemorySegmentrepresenting the target address of the foreign function is theMemorySegment.NULLaddress. If an argument is aMemorySegment, whose corresponding layout is a group layout, the linker might attempt to access the contents of the segment. As such, one of the exceptions specified by theMemorySegment.get(ValueLayout.OfByte, long)or theMemorySegment.copy(MemorySegment, long, MemorySegment, long, long)methods may be thrown. If an argument is aMemorySegmentwhose corresponding layout is an address layout, the linker will throw anIllegalArgumentExceptionif the segment is a heap memory segment, unless heap memory segments are explicitly allowed through theLinker.Option.critical(boolean)linker option. The returned method handle will additionally throwNullPointerExceptionif any argument passed to it isnull.- Parameters:
- function- the function descriptor of the target foreign function
- options- the linker options associated with this linkage request
- Returns:
- a downcall method handle
- Throws:
- IllegalArgumentException- if the provided function descriptor is not supported by this linker
- IllegalArgumentException- if an invalid combination of linker options is given
- IllegalCallerException- if the caller is in a module that does not have native access enabled
 
- 
upcallStubMemorySegment upcallStub(MethodHandle target, FunctionDescriptor function, Arena arena, Linker.Option... options) upcallStubis a restricted method of the Java platform.Programs can only useupcallStubwhen access to restricted methods is enabled.Restricted methods are unsafe, and, if used incorrectly, might crash the JVM or result in memory corruption.Creates an upcall stub which can be passed to other foreign functions as a function pointer, associated with the given arena. Calling such a function pointer from foreign code will result in the execution of the provided method handle.The returned memory segment's address points to the newly allocated upcall stub, and is associated with the provided arena. As such, the lifetime of the returned upcall stub segment is controlled by the provided arena. For instance, if the provided arena is a confined arena, the returned upcall stub segment will be deallocated when the provided confined arena is closed. An upcall stub argument whose corresponding layout is an address layout is a native segment associated with the global scope. Under normal conditions, the size of this segment argument is 0. However, if the address layout has a target layoutT, then the size of the segment argument is set toT.byteSize().The target method handle should not throw any exceptions. If the target method handle does throw an exception, the JVM will terminate abruptly. To avoid this, clients should wrap the code in the target method handle in a try/catch block to catch any unexpected exceptions. This can be done using the MethodHandles.catchException(MethodHandle, Class, MethodHandle)method handle combinator, and handle exceptions as desired in the corresponding catch block.- Parameters:
- target- the target method handle
- function- the upcall stub function descriptor
- arena- the arena associated with the returned upcall stub segment
- options- the linker options associated with this linkage request
- Returns:
- a zero-length segment whose address is the address of the upcall stub
- Throws:
- IllegalArgumentException- if the provided function descriptor is not supported by this linker
- IllegalArgumentException- if the type of- targetis incompatible with the type derived from- function
- IllegalArgumentException- if it is determined that the target method handle can throw an exception
- IllegalStateException- if- arena.scope().isAlive() == false
- WrongThreadException- if- arenais a confined arena, and this method is called from a thread- T, other than the arena's owner thread
- IllegalCallerException- if the caller is in a module that does not have native access enabled
 
- 
defaultLookupSymbolLookup defaultLookup()Returns a symbol lookup for symbols in a set of commonly used libraries.Each Linkeris responsible for choosing libraries that are widely recognized as useful on the OS and processor combination supported by theLinker. Accordingly, the precise set of symbols exposed by the symbol lookup is unspecified; it varies from oneLinkerto another.- Implementation Note:
- It is strongly recommended that the result of defaultLookup()exposes a set of symbols that is stable over time. Clients ofdefaultLookup()are likely to fail if a symbol that was previously exposed by the symbol lookup is no longer exposed.If an implementer provides Linkerimplementations for multiple OS and processor combinations, then it is strongly recommended that the result ofdefaultLookup()exposes, as much as possible, a consistent set of symbols across all the OS and processor combinations.
- Returns:
- a symbol lookup for symbols in a set of commonly used libraries
 
- 
canonicalLayoutsMap<String, MemoryLayout> canonicalLayouts()Returns an unmodifiable mapping between the names of data types used by the ABI implemented by this linker and their canonical layouts.Each Linkeris responsible for choosing the data types that are widely recognized as useful on the OS and processor combination supported by theLinker. Accordingly, the precise set of data type names and canonical layouts exposed by the linker are unspecified; they vary from oneLinkerto another.- Implementation Note:
- It is strongly recommended that the result of canonicalLayouts()exposes a set of symbols that is stable over time. Clients ofcanonicalLayouts()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.If an implementer provides Linkerimplementations for multiple OS and processor combinations, then it is strongly recommended that the result ofcanonicalLayouts()exposes, as much as possible, a consistent set of symbols across all the OS and processor combinations.
- Returns:
- an unmodifiable mapping between the names of data types used by the ABI implemented by this linker and their canonical layouts
 
 
- 
downcallHandlewhen access to restricted methods is enabled.