APIdia Launch Partner
Top Description Methods
java.lang.foreign

public Interface SymbolLookup

Known Direct Implementers
jdk.internal.foreign.SystemLookup
Annotations
@FunctionalInterface
Imports
jdk.internal.access.JavaLangAccess, .SharedSecrets, jdk.internal.foreign.MemorySessionImpl, .Utils, jdk.internal.javac.Restricted, jdk.internal.loader.BuiltinClassLoader, .NativeLibraries, .NativeLibrary, .RawNativeLibraries, jdk.internal.reflect.CallerSensitive, .Reflection, java.lang.invoke.MethodHandles, java.nio.file.FileSystems, .Path, java.util.NoSuchElementException, .Objects, .Optional, java.util.function.BiFunction

A symbol lookup retrieves the address of a symbol in one or more libraries. A symbol is a named entity, such as a function or a global variable.

A symbol lookup is created with respect to a particular library (or libraries). Subsequently, the SymbolLookup#find(String) method takes the name of a symbol and returns the address of the symbol in that library.

The address of a symbol is modeled as a zero-length memory segment. The segment can be used in different ways:

Obtaining a symbol lookup

The factory methods libraryLookup(String, Arena) and libraryLookup(Path, Arena) create a symbol lookup for a library known to the operating system. The library is specified by either its name or a path. The library is loaded if not already loaded. The symbol lookup, which is known as a library lookup, and its lifetime is controlled by an arena. For instance, if the provided arena is a confined arena, the library associated with the symbol lookup is unloaded when the confined arena is closed:
try (Arena arena = Arena.ofConfined()) { SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so", arena); // libGL.so loaded here MemorySegment glGetString = libGL.findOrThrow("glGetString"); ... } // libGL.so unloaded here
try (Arena arena = Arena.ofConfined()) {
    SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so", arena); // libGL.so loaded here
    MemorySegment glGetString = libGL.findOrThrow("glGetString");
    ...
} //  libGL.so unloaded here

If a library was previously loaded through JNI, i.e., by System#load(String) or System#loadLibrary(String), then the library was also associated with a particular class loader. The factory method loaderLookup() creates a symbol lookup for all the libraries associated with the caller's class loader:

System.loadLibrary("GL"); // libGL.so loaded here ... SymbolLookup libGL = SymbolLookup.loaderLookup(); MemorySegment glGetString = libGL.findOrThrow("glGetString");
System.loadLibrary("GL"); // libGL.so loaded here
...
SymbolLookup libGL = SymbolLookup.loaderLookup();
MemorySegment glGetString = libGL.findOrThrow("glGetString");
This symbol lookup, which is known as a loader lookup, is dynamic with respect to the libraries associated with the class loader. If other libraries are subsequently loaded through JNI and associated with the class loader, then the loader lookup will expose their symbols automatically.

Note that a loader lookup only exposes symbols in libraries that were previously loaded through JNI, i.e., by System#load(String) or System#loadLibrary(String). A loader lookup does not expose symbols in libraries that were loaded in the course of creating a library lookup:

libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true loaderLookup().find("glGetString").isPresent(); // false
libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
loaderLookup().find("glGetString").isPresent(); // false
Note also that a library lookup for library L exposes symbols in L even if L was previously loaded through JNI (the association with a class loader is immaterial to the library lookup):
System.loadLibrary("GL"); // libGL.so loaded here libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
System.loadLibrary("GL"); // libGL.so loaded here
libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true

Finally, each Linker provides a symbol lookup for libraries that are commonly used on the OS and processor combination supported by that Linker. This symbol lookup, which is known as a default lookup, helps clients to quickly find addresses of well-known symbols. For example, a Linker for Linux/x64 might choose to expose symbols in libc through the default lookup:

Linker nativeLinker = Linker.nativeLinker(); SymbolLookup stdlib = nativeLinker.defaultLookup(); MemorySegment malloc = stdlib.findOrThrow("malloc");
Linker nativeLinker = Linker.nativeLinker();
SymbolLookup stdlib = nativeLinker.defaultLookup();
MemorySegment malloc = stdlib.findOrThrow("malloc");
Since
22

Method Summary

Modifier and TypeMethod and Description
public Optional<MemorySegment>

Returns:

a zero-length memory segment whose address indicates the address of the symbol, if found
find
(String
the symbol name
name
)

Returns the address of the symbol with the given name.

public default MemorySegment

Returns:

a zero-length memory segment whose address indicates the address of the symbol
findOrThrow
(String
the symbol name
name
)

Returns the address of the symbol with the given name or throws an exception.

public static SymbolLookup

Returns:

a new symbol lookup suitable to find symbols in a library with the given name
libraryLookup
(String
the name of the library in which symbols should be looked up
name
,
Arena
the arena associated with symbols obtained from the returned lookup
arena
)

Loads a library with the given name (if not already loaded) and creates a symbol lookup for symbols in that library.

public static SymbolLookup

Returns:

a new symbol lookup suitable to find symbols in a library with the given path
libraryLookup
(Path
the path of the library in which symbols should be looked up
path
,
Arena
the arena associated with symbols obtained from the returned lookup
arena
)

Loads a library from the given path (if not already loaded) and creates a symbol lookup for symbols in that library.

private static <Z> SymbolLookup
libraryLookup(Z libDesc, BiFunction<RawNativeLibraries, Z, NativeLibrary> loadLibraryFunc, Arena libArena)

public static SymbolLookup

Returns:

a symbol lookup for symbols in the libraries associated with the caller's class loader
loaderLookup
()

Returns a symbol lookup for symbols in the libraries associated with the caller's class loader.

public default SymbolLookup

Returns:

a composed symbol lookup that returns the result of finding the symbol with this lookup if found, otherwise returns the result of finding the symbol with the other lookup
or
(SymbolLookup
the symbol lookup that should be used to look for symbols not found in this lookup
other
)

Returns a composed symbol lookup that returns the result of finding the symbol with this lookup if found, otherwise returns the result of finding the symbol with the other lookup.

Method Detail

findback to summary
public Optional<MemorySegment> find(String name)

Returns the address of the symbol with the given name.

Parameters
name:String

the symbol name

Returns:Optional<MemorySegment>

a zero-length memory segment whose address indicates the address of the symbol, if found

See Also
findOrThrow(String)
findOrThrowback to summary
public default MemorySegment findOrThrow(String name)

Returns the address of the symbol with the given name or throws an exception.

This is equivalent to the following code, but is more efficient: to:

String name = ... MemorySegment address = lookup.find(name) .orElseThrow(() -> new NoSuchElementException("Symbol not found: " + name));
String name = ...
MemorySegment address = lookup.find(name)
    .orElseThrow(() -> new NoSuchElementException("Symbol not found: " + name));
Parameters
name:String

the symbol name

Returns:MemorySegment

a zero-length memory segment whose address indicates the address of the symbol

Exceptions
NoSuchElementException:
if no symbol address can be found for the given name
Since
23
See Also
find(String)
libraryLookupback to summary
public static SymbolLookup libraryLookup(String name, Arena arena)

Loads a library with the given name (if not already loaded) and creates a symbol lookup for symbols in that library. The lifetime of the returned library lookup is controlled by the provided arena. For instance, if the provided arena is a confined arena, the library associated with the returned lookup will be unloaded when the provided confined arena is closed.

Implementation Note

The process of resolving a library name is OS-specific. For instance, in a POSIX-compliant OS, the library name is resolved according to the specification of the dlopen function for that OS. In Windows, the library name is resolved according to the specification of the LoadLibrary function.

Parameters
name:String

the name of the library in which symbols should be looked up

arena:Arena

the arena associated with symbols obtained from the returned lookup

Returns:SymbolLookup

a new symbol lookup suitable to find symbols in a library with the given name

Annotations
@CallerSensitive
@Restricted
Exceptions
IllegalStateException:
if arena.scope().isAlive() == false
WrongThreadException:
if arena is a confined arena, and this method is called from a thread T, other than the arena's owner thread
IllegalArgumentException:
if name does not identify a valid library
IllegalCallerException:
if the caller is in a module that does not have native access enabled
libraryLookupback to summary
public static SymbolLookup libraryLookup(Path path, Arena arena)

Loads a library from the given path (if not already loaded) and creates a symbol lookup for symbols in that library. The lifetime of the returned library lookup is controlled by the provided arena. For instance, if the provided arena is a confined arena, the library associated with the returned lookup will be unloaded when the provided confined arena is closed.

Implementation Note

On Linux, the functionalities provided by this factory method and the returned symbol lookup are implemented using the dlopen, dlsym and dlclose functions.

Parameters
path:Path

the path of the library in which symbols should be looked up

arena:Arena

the arena associated with symbols obtained from the returned lookup

Returns:SymbolLookup

a new symbol lookup suitable to find symbols in a library with the given path

Annotations
@CallerSensitive
@Restricted
Exceptions
IllegalStateException:
if arena.scope().isAlive() == false
WrongThreadException:
if arena is a confined arena, and this method is called from a thread T, other than the arena's owner thread
IllegalArgumentException:
if path does not point to a valid library in the default file system
IllegalCallerException:
if the caller is in a module that does not have native access enabled
libraryLookupback to summary
private static <Z> SymbolLookup libraryLookup(Z libDesc, BiFunction<RawNativeLibraries, Z, NativeLibrary> loadLibraryFunc, Arena libArena)
Annotations
@SuppressWarnings:restricted
loaderLookupback to summary
public static SymbolLookup loaderLookup()

Returns a symbol lookup for symbols in the libraries associated with the caller's class loader.

A library is associated with a class loader CL when the library is loaded via an invocation of System#load(String) or System#loadLibrary(String) from code in a class defined by CL. If that code makes further invocations of System#load(String) or System#loadLibrary(String) then more libraries are loaded and associated with CL. The symbol lookup returned by this method is always current: it reflects all the libraries associated with the relevant class loader, even if they were loaded after this method returned.

Libraries associated with a class loader are unloaded when the class loader becomes unreachable. The symbol lookup returned by this method is associated with an automatic scope which keeps the caller's class loader reachable. Therefore, libraries associated with the caller's class loader are kept loaded (and their symbols available) as long as a loader lookup for that class loader, or any of the segments obtained by it, is reachable.

In cases where this method is called from a context where there is no caller frame on the stack (e.g. when called directly from a JNI attached thread), the caller's class loader defaults to the system class loader.

Returns:SymbolLookup

a symbol lookup for symbols in the libraries associated with the caller's class loader

Annotations
@CallerSensitive
@SuppressWarnings:restricted
See Also
System#load(String), System#loadLibrary(String)
orback to summary
public default SymbolLookup or(SymbolLookup other)

Returns a composed symbol lookup that returns the result of finding the symbol with this lookup if found, otherwise returns the result of finding the symbol with the other lookup.

API Note

This method could be used to chain multiple symbol lookups together, e.g. so that symbols could be retrieved, in order, from multiple libraries:

var lookup = SymbolLookup.libraryLookup("foo", arena) .or(SymbolLookup.libraryLookup("bar", arena)) .or(SymbolLookup.loaderLookup());
var lookup = SymbolLookup.libraryLookup("foo", arena)
        .or(SymbolLookup.libraryLookup("bar", arena))
        .or(SymbolLookup.loaderLookup());
The above code creates a symbol lookup that first searches for symbols in the "foo" library. If no symbol is found in "foo" then "bar" is searched. Finally, if a symbol is neither found in "foo" nor in "bar", the loader lookup is used.
Parameters
other:SymbolLookup

the symbol lookup that should be used to look for symbols not found in this lookup

Returns:SymbolLookup

a composed symbol lookup that returns the result of finding the symbol with this lookup if found, otherwise returns the result of finding the symbol with the other lookup