-
CSR
-
Resolution: Approved
-
P3
-
None
-
source
-
minimal
-
-
Java API
-
SE
Summary
Add a default method SymbolLookup.findOrThrow(String name)
that will throw an exception with a useful message if a symbol is not found.
Problem
It is a common pattern to call symbolLookup.find(name).orElseThrow()
or symbolLookup.find(name).get()
in order to obtain a symbol. In the case that a symbol cannot be found, the exception thrown above does not provide the given name
in its description. Using symbolLookup.find(name).orElseThrow(() -> ... name ...)
would incur a capturing lambda being created.
Solution
Add a method that will provide a relevant exception message, should a symbol not be found. The method does not incur lambda capturing internally.
Specification
diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java
index 9bfc7964322e1..3bc416b9c6272 100644
--- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java
+++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java
@@ -39,6 +39,7 @@
import java.lang.invoke.MethodHandles;
import java.nio.file.FileSystems;
import java.nio.file.Path;
+import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiFunction;
@@ -79,7 +80,7 @@
* {@snippet lang = java:
* try (Arena arena = Arena.ofConfined()) {
* SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so", arena); // libGL.so loaded here
- * MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
+ * MemorySegment glGetString = libGL.findOrThrow("glGetString");
* ...
* } // libGL.so unloaded here
*}
@@ -93,7 +94,7 @@
* System.loadLibrary("GL"); // libGL.so loaded here
* ...
* SymbolLookup libGL = SymbolLookup.loaderLookup();
- * MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
+ * MemorySegment glGetString = libGL.findOrThrow("glGetString");
* }
*
* This symbol lookup, which is known as a loader lookup, is dynamic with
@@ -130,7 +131,7 @@
* {@snippet lang = java:
* Linker nativeLinker = Linker.nativeLinker();
* SymbolLookup stdlib = nativeLinker.defaultLookup();
- * MemorySegment malloc = stdlib.find("malloc").orElseThrow();
+ * MemorySegment malloc = stdlib.findOrThrow("malloc");
*}
*
* @since 22
@@ -144,9 +145,40 @@ public interface SymbolLookup {
* @param name the symbol name
* @return a zero-length memory segment whose address indicates the address of
* the symbol, if found
+ * @see #findOrThrow(String)
*/
Optional find(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:
+ * {@snippet lang= java :
+ * String name = ...
+ * MemorySegment address = lookup.find(name)
+ * .orElseThrow(() -> new NoSuchElementException("Symbol not found: " + name));
+ * }
+ *
+ * @param name the symbol name
+ * @return a zero-length memory segment whose address indicates the address of
+ * the symbol
+ * @throws NoSuchElementException if no symbol address can be found for the
+ * given name
+ * @see #find(String)
+ *
+ * @since 23
+ */
+ default MemorySegment findOrThrow(String name) {
+ Objects.requireNonNull(name);
+ Optional address = find(name);
+ // Avoid lambda capturing
+ if (address.isPresent()) {
+ return address.get();
+ }
+ throw new NoSuchElementException("Symbol not found: " + name);
+ }
+
/**
* {@return a composed symbol lookup that returns the result of finding the symbol
* with this lookup if found, otherwise returns the result of finding
diff --git a/src/java.base/share/classes/java/lang/foreign/package-info.java b/src/java.base/share/classes/java/lang/foreign/package-info.java
index b2a6a5f447440..6594826e40524 100644
--- a/src/java.base/share/classes/java/lang/foreign/package-info.java
+++ b/src/java.base/share/classes/java/lang/foreign/package-info.java
@@ -100,7 +100,7 @@
* Linker linker = Linker.nativeLinker();
* SymbolLookup stdlib = linker.defaultLookup();
* MethodHandle strlen = linker.downcallHandle(
- * stdlib.find("strlen").orElseThrow(),
+ * stdlib.findOrThrow("strlen"),
* FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
* );
*
@@ -111,7 +111,7 @@
*}
*
* Here, we obtain a {@linkplain java.lang.foreign.Linker#nativeLinker() native linker}
- * and we use it to {@linkplain java.lang.foreign.SymbolLookup#find(java.lang.String) look up}
+ * and we use it to {@linkplain java.lang.foreign.SymbolLookup#findOrThrow(java.lang.String) look up}
* the {@code strlen} function in the standard C library; a downcall method handle
* targeting said function is subsequently
* {@linkplain java.lang.foreign.Linker#downcallHandle(FunctionDescriptor, Linker.Option...) obtained}.
- csr of
-
JDK-8314592 Add shortcut to SymbolLookup::find
- Resolved