1 /*
  2  * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.foreign.snippets;
 27 
 28 import java.lang.foreign.AddressLayout;
 29 import java.lang.foreign.Arena;
 30 import java.lang.foreign.FunctionDescriptor;
 31 import java.lang.foreign.Linker;
 32 import java.lang.foreign.MemoryLayout;
 33 import java.lang.foreign.MemorySegment;
 34 import java.lang.foreign.SegmentAllocator;
 35 import java.lang.foreign.SequenceLayout;
 36 import java.lang.foreign.StructLayout;
 37 import java.lang.foreign.SymbolLookup;
 38 import java.lang.foreign.ValueLayout;
 39 import java.lang.invoke.MethodHandle;
 40 import java.lang.invoke.MethodHandles;
 41 import java.lang.invoke.MethodType;
 42 import java.lang.invoke.VarHandle;
 43 import java.nio.ByteOrder;
 44 import java.util.Objects;
 45 import java.util.Optional;
 46 import java.util.stream.Collectors;
 47 import java.util.stream.StreamSupport;
 48 
 49 import static java.lang.foreign.MemoryLayout.sequenceLayout;
 50 import static java.lang.foreign.MemoryLayout.structLayout;
 51 import static java.lang.foreign.SymbolLookup.libraryLookup;
 52 import static java.lang.foreign.SymbolLookup.loaderLookup;
 53 import static java.lang.foreign.ValueLayout.*;
 54 import static java.nio.ByteOrder.BIG_ENDIAN;
 55 
 56 /**
 57  * Snippets for the java.lang.foreign documentation.
 58  */
 59 class Snippets {
 60 
 61     /**
 62      * Creates a new snippet.
 63      */
 64     public Snippets() {
 65     }
 66 
 67     static class ArenaSnippets {
 68 
 69         void globalArena() {
 70             // @start region="global-allocation":
 71             MemorySegment segment = Arena.global().allocate(100, 1); // @highlight regex='global()'
 72             // ...
 73             // segment is never deallocated!
 74             // @end
 75         }
 76 
 77         void autoArena() {
 78             // @start region="auto-allocation":
 79             MemorySegment segment = Arena.ofAuto().allocate(100, 1); // @highlight regex='ofAuto()'
 80             // ...
 81             segment = null; // the segment region becomes available for deallocation after this point
 82             // @end
 83         }
 84 
 85         void confinedArena() {
 86             // @start region="confined-allocation":
 87             MemorySegment segment = null;
 88             try (Arena arena = Arena.ofConfined()) { // @highlight regex='ofConfined()'
 89                 segment = arena.allocate(100);
 90                 // ...
 91             } // segment region deallocated here
 92             segment.get(ValueLayout.JAVA_BYTE, 0); // throws IllegalStateException
 93             // @end
 94         }
 95 
 96         static
 97         // @start region="slicing-arena":
 98         class SlicingArena implements Arena {
 99             final Arena arena = Arena.ofConfined();
100             final SegmentAllocator slicingAllocator;
101 
102             SlicingArena(long size) {
103                 slicingAllocator = SegmentAllocator.slicingAllocator(arena.allocate(size));
104             }
105 
106             public MemorySegment allocate(long byteSize, long byteAlignment) {
107                 return slicingAllocator.allocate(byteSize, byteAlignment);
108             }
109 
110             public MemorySegment.Scope scope() {
111                 return arena.scope();
112             }
113 
114             public void close() {
115                 arena.close();
116             }
117 
118         }
119         // @end
120 
121         public static void main(String[] args) {
122             // @start region="slicing-arena-main":
123             try (Arena slicingArena = new SlicingArena(1000)) {
124                 for (int i = 0; i < 10; i++) {
125                     MemorySegment s = slicingArena.allocateFrom(JAVA_INT, 1, 2, 3, 4, 5);
126                     // ...
127                 }
128             } // all memory allocated is released here
129             // @end
130         }
131 
132         void arenaOverlap() {
133             try (var arena = Arena.ofConfined()) {
134                 var S1 = arena.allocate(16L);
135                 var S2 = arena.allocate(16L);
136 
137                 if (
138                     // @start region="arena-overlap":
139                         S1.asOverlappingSlice(S2).isEmpty() == true
140                     // @end
141                 ) {}
142 
143             }
144         }
145     }
146 
147     static class AddressLayoutSnippets {
148         void withTargetLayout() {
149             AddressLayout addressLayout = ADDRESS;
150             AddressLayout unboundedLayout = addressLayout.withTargetLayout(
151                     sequenceLayout(Long.MAX_VALUE, ValueLayout.JAVA_BYTE));
152         }
153     }
154 
155     static class FunctionDescriptionSnippets {
156     }
157 
158     static class GroupLayoutSnippets {
159     }
160 
161     static class LinkerSnippets {
162 
163         void downcall() throws Throwable {
164             Linker linker = Linker.nativeLinker();
165             MethodHandle strlen = linker.downcallHandle(
166                     linker.defaultLookup().find("strlen").orElseThrow(),
167                     FunctionDescriptor.of(JAVA_LONG, ADDRESS)
168             );
169 
170             try (Arena arena = Arena.ofConfined()) {
171                 MemorySegment str = arena.allocateFrom("Hello");
172                 long len = (long) strlen.invokeExact(str);  // 5
173             }
174 
175         }
176 
177         void qsort() throws Throwable {
178             Linker linker = Linker.nativeLinker();
179             MethodHandle qsort = linker.downcallHandle(
180                     linker.defaultLookup().find("qsort").orElseThrow(),
181                     FunctionDescriptor.ofVoid(ADDRESS, JAVA_LONG, JAVA_LONG, ADDRESS)
182             );
183 
184             class Qsort {
185                 static int qsortCompare(MemorySegment elem1, MemorySegment elem2) {
186                     return Integer.compare(elem1.get(JAVA_INT, 0), elem2.get(JAVA_INT, 0));
187                 }
188             }
189 
190             FunctionDescriptor comparDesc = FunctionDescriptor.of(JAVA_INT,
191                     ADDRESS.withTargetLayout(JAVA_INT),
192                     ADDRESS.withTargetLayout(JAVA_INT));
193             MethodHandle comparHandle = MethodHandles.lookup()
194                     .findStatic(Qsort.class, "qsortCompare",
195                             comparDesc.toMethodType());
196 
197 
198             try (Arena arena = Arena.ofConfined()) {
199                 MemorySegment compareFunc = linker.upcallStub(comparHandle, comparDesc, arena);
200                 MemorySegment array = arena.allocateFrom(JAVA_INT, 0, 9, 3, 4, 6, 5, 1, 8, 2, 7);
201                 qsort.invokeExact(array, 10L, 4L, compareFunc);
202                 int[] sorted = array.toArray(JAVA_INT); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
203 
204             }
205         }
206 
207         void returnPointer() throws Throwable {
208             Linker linker = Linker.nativeLinker();
209 
210             MethodHandle malloc = linker.downcallHandle(
211                     linker.defaultLookup().find("malloc").orElseThrow(),
212                     FunctionDescriptor.of(ADDRESS, JAVA_LONG)
213             );
214 
215             MethodHandle free = linker.downcallHandle(
216                     linker.defaultLookup().find("free").orElseThrow(),
217                     FunctionDescriptor.ofVoid(ADDRESS)
218             );
219 
220             MemorySegment segment = (MemorySegment) malloc.invokeExact(100);
221 
222             class AllocateMemory {
223 
224                 MemorySegment allocateMemory(long byteSize, Arena arena) throws Throwable {
225                     MemorySegment segment = (MemorySegment) malloc.invokeExact(byteSize); // size = 0, scope = always alive
226                     return segment.reinterpret(byteSize, arena, s -> {
227                         try {
228                             free.invokeExact(s);
229                         } catch (Throwable e) {
230                             throw new RuntimeException(e);
231                         }
232                     });  // size = byteSize, scope = arena.scope()
233                 }
234 
235             }
236 
237 
238             class AllocateMemory2 {
239 
240                 MemorySegment allocateMemory(long byteSize, Arena arena) {
241                     MemorySegment segment = trySupplier(() -> (MemorySegment) malloc.invokeExact(byteSize));   // size = 0, scope = always alive
242                     return segment.reinterpret(byteSize, arena, s -> trySupplier(() -> free.invokeExact(s)));  // size = byteSize, scope = arena.scope()
243                 }
244 
245                 @FunctionalInterface
246                 interface ThrowingSupplier<T> {
247                     T get() throws Throwable;
248 
249                 }
250 
251                 <T> T trySupplier(ThrowingSupplier<? extends T> supplier) {
252                     try {
253                         return supplier.get();
254                     } catch (Throwable t) {
255                         throw new RuntimeException(t);
256                     }
257                 }
258 
259 
260             }
261 
262 
263             class AllocateMemory3 {
264 
265                 MemorySegment allocateMemory(long byteSize, Arena arena) throws Throwable {
266                     MemorySegment segment = (MemorySegment) malloc.invokeExact(byteSize); // size = 0, scope = always alive
267                     return segment.reinterpret(byteSize, arena, this::freeMemory);        // size = byteSize, scope = arena.scope()
268                 }
269 
270                 void freeMemory(MemorySegment segment) {
271                     try {
272                         free.invokeExact(segment);
273                     } catch (Throwable e) {
274                         throw new RuntimeException(e);
275                     }
276                 }
277             }
278 
279         }
280 
281         void variadicFunc() throws Throwable {
282 
283             Linker linker = Linker.nativeLinker();
284             MethodHandle printf = linker.downcallHandle(
285                     linker.defaultLookup().find("printf").orElseThrow(),
286                     FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_INT, JAVA_INT, JAVA_INT),
287                     Linker.Option.firstVariadicArg(1) // first int is variadic
288             );
289 
290             try (Arena arena = Arena.ofConfined()) {
291                 int res = (int) printf.invokeExact(arena.allocateFrom("%d plus %d equals %d"), 2, 2, 4); //prints "2 plus 2 equals 4"
292             }
293 
294         }
295 
296         void downcallHandle() {
297             Linker linker = Linker.nativeLinker();
298             FunctionDescriptor function = null;
299             MemorySegment symbol = null;
300 
301             linker.downcallHandle(function).bindTo(symbol);
302 
303         }
304 
305         void captureCallState() throws Throwable {
306 
307             MemorySegment targetAddress = null; // ...
308             Linker.Option ccs = Linker.Option.captureCallState("errno");
309             MethodHandle handle = Linker.nativeLinker().downcallHandle(targetAddress, FunctionDescriptor.ofVoid(), ccs);
310 
311             StructLayout capturedStateLayout = Linker.Option.captureStateLayout();
312             VarHandle errnoHandle = capturedStateLayout.varHandle(PathElement.groupElement("errno"));
313             try (Arena arena = Arena.ofConfined()) {
314                 MemorySegment capturedState = arena.allocate(capturedStateLayout);
315                 handle.invoke(capturedState);
316                 int errno = (int) errnoHandle.get(capturedState, 0L);
317                 // use errno
318             }
319         }
320 
321         void captureStateLayout() {
322             String capturedNames = Linker.Option.captureStateLayout().memberLayouts().stream()
323                     .map(MemoryLayout::name)
324                     .flatMap(Optional::stream)
325                     .map(Objects::toString)
326                     .collect(Collectors.joining(", "));
327         }
328 
329 
330     }
331 
332     static class MemoryLayoutSnippets {
333 
334         void header() throws Throwable {
335             SequenceLayout taggedValues = sequenceLayout(5,
336                     structLayout(
337                             ValueLayout.JAVA_BYTE.withName("kind"),
338                             MemoryLayout.paddingLayout(24),
339                             ValueLayout.JAVA_INT.withName("value")
340                     )
341             ).withName("TaggedValues");
342 
343             long valueOffset = taggedValues.byteOffset(PathElement.sequenceElement(0),
344                     PathElement.groupElement("value")); // yields 4
345 
346             MemoryLayout value = taggedValues.select(PathElement.sequenceElement(),
347                     PathElement.groupElement("value"));
348 
349             VarHandle valueHandle = taggedValues.varHandle(PathElement.sequenceElement(),
350                     PathElement.groupElement("value"));
351 
352             MethodHandle offsetHandle = taggedValues.byteOffsetHandle(PathElement.sequenceElement(),
353                     PathElement.groupElement("kind"));
354             long offset1 = (long) offsetHandle.invokeExact(0L, 1L); // 8
355             long offset2 = (long) offsetHandle.invokeExact(0L, 2L); // 16
356         }
357 
358         void sliceHandle() {
359             MemorySegment segment = null;
360             long offset = 0;
361             MemoryLayout layout = null;
362 
363             segment.asSlice(offset, layout.byteSize());
364         }
365 
366         void sequenceLayout0() {
367             MemoryLayout elementLayout = JAVA_INT;
368 
369             sequenceLayout(Long.MAX_VALUE / elementLayout.byteSize(), elementLayout);
370         }
371 
372         void structLayout0() {
373             MemoryLayout elementLayout = JAVA_INT;
374 
375             structLayout(JAVA_SHORT, JAVA_INT);
376             structLayout(JAVA_SHORT, MemoryLayout.paddingLayout(16), JAVA_INT);
377             structLayout(JAVA_SHORT, JAVA_INT.withByteAlignment(2));
378         }
379 
380     }
381 
382     static class MemorySegmentSnippets {
383         void header() throws NoSuchMethodException, IllegalAccessException {
384 
385             {
386                 MemorySegment segment = null; // ...
387                 int value = segment.get(ValueLayout.JAVA_INT, 0);
388             }
389 
390             {
391                 MemorySegment segment = null; // ...
392 
393                 int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0);
394             }
395 
396             {
397                 MemorySegment segment = null; // ...
398 
399                 VarHandle intHandle = ValueLayout.JAVA_INT.varHandle();
400                 MethodHandle multiplyExact = MethodHandles.lookup()
401                         .findStatic(Math.class, "multiplyExact",
402                                 MethodType.methodType(long.class, long.class, long.class));
403                 intHandle = MethodHandles.filterCoordinates(intHandle, 1,
404                         MethodHandles.insertArguments(multiplyExact, 0, ValueLayout.JAVA_INT.byteSize()));
405                 int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
406             }
407 
408             {
409                 MemorySegment segment = null; // ...
410 
411                 MemoryLayout segmentLayout = MemoryLayout.structLayout(
412                     ValueLayout.JAVA_INT.withName("size"),
413                     MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT).withName("data") // array of 4 elements
414                 );
415                 VarHandle intHandle = segmentLayout.varHandle(MemoryLayout.PathElement.groupElement("data"),
416                                                               MemoryLayout.PathElement.sequenceElement());
417                 int value = (int) intHandle.get(segment, 0L, 3L); // get int element at offset 0 + offsetof(data) + 3 * 4 = 12
418             }
419 
420             {
421                 Arena arena = Arena.ofConfined();
422                 MemorySegment segment = arena.allocate(100);
423                 MemorySegment slice = segment.asSlice(50, 10);
424                 slice.get(ValueLayout.JAVA_INT, 20); // Out of bounds!
425                 arena.close();
426                 slice.get(ValueLayout.JAVA_INT, 0); // Already closed!
427             }
428 
429 
430             {
431                 try (Arena arena = Arena.ofShared()) {
432                     SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
433                     MemorySegment segment = arena.allocate(SEQUENCE_LAYOUT);
434                     int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
435                             .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
436                             .sum();
437                 }
438             }
439 
440             {
441                 MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
442                 byteSegment.get(ValueLayout.JAVA_INT, 0); // fails: layout alignment is 4, segment max alignment is 1
443             }
444 
445             {
446                 MemorySegment longSegment = MemorySegment.ofArray(new long[10]);
447                 longSegment.get(ValueLayout.JAVA_INT, 0); // ok: layout alignment is 4, segment max alignment is 8
448             }
449 
450             {
451                 MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
452                 byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: layout alignment is 1, segment max alignment is 1
453             }
454 
455             {
456                 MemorySegment segment = null;
457                 long offset = 42;
458 
459                 MemorySegment z = segment.get(ValueLayout.ADDRESS, offset);   // size = 0
460                 MemorySegment ptr = z.reinterpret(16);                // size = 16
461                 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);        // ok
462             }
463 
464             {
465                 MemorySegment segment = null;
466                 long offset = 42;
467 
468                 MemorySegment ptr = null;
469                 try (Arena arena = Arena.ofConfined()) {
470                     MemorySegment z = segment.get(ValueLayout.ADDRESS, offset);   // size = 0, scope = always alive
471                     ptr = z.reinterpret(16, arena, null);          // size = 4, scope = arena.scope()
472                     int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);        // ok
473                 }
474                 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);            // throws IllegalStateException
475             }
476 
477             {
478                 MemorySegment segment = null;
479                 long offset = 42;
480 
481                 AddressLayout intArrPtrLayout = ValueLayout.ADDRESS.withTargetLayout(
482                         MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT)); // layout for int (*ptr)[4]
483                 MemorySegment ptr = segment.get(intArrPtrLayout, offset);                  // size = 16
484                 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);                     // ok
485             }
486 
487 
488         }
489 
490         boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) {
491             return ((segment.address() + offset) % layout.byteAlignment()) == 0;
492         }
493 
494         void elements() {
495             MemorySegment segment = null;
496             MemoryLayout elementLayout = JAVA_INT;
497 
498             StreamSupport.stream(segment.spliterator(elementLayout), false);
499         }
500 
501         void asSlice() {
502             MemorySegment segment = null;
503             long offset = 42;
504             MemoryLayout layout = JAVA_INT;
505 
506             segment.asSlice(offset, layout.byteSize(), 1);
507 
508             segment.asSlice(offset, layout.byteSize(), layout.byteAlignment());
509 
510             segment.asSlice(offset, segment.byteSize() - offset);
511 
512         }
513 
514         void reinterpret() {
515             MemorySegment segment = null;
516 
517             MemorySegment cleanupSegment = MemorySegment.ofAddress(segment.address());
518 
519         }
520 
521         void segmentOffset() {
522             MemorySegment segment = null;
523             MemorySegment other = null;
524 
525             long offset = other.address() - segment.address();
526         }
527 
528         void fill() {
529             MemorySegment segment = null;
530             byte value = 42;
531 
532             for (long l = 0; l < segment.byteSize(); l++) {
533                 segment.set(JAVA_BYTE, l, value);
534             }
535         }
536 
537         void copyFrom() {
538             MemorySegment src = null;
539             MemorySegment dst = null;
540 
541             // MemorySegment.copy(src, 0, this, 0, src.byteSize());
542             MemorySegment.copy(src, 0, dst, 0, src.byteSize());
543         }
544 
545         void copy() {
546             MemorySegment srcSegment = null;
547             long srcOffset = 42;
548             MemorySegment dstSegment = null;
549             long dstOffset = 13;
550             long bytes = 3;
551 
552             MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes);
553         }
554 
555 
556     }
557 
558     static class PackageInfoSnippets {
559 
560         void header() throws Throwable {
561             try (Arena arena = Arena.ofConfined()) {
562                 MemorySegment segment = arena.allocate(10 * 4);
563                 for (int i = 0; i < 10; i++) {
564                     segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
565                 }
566             }
567 
568             Linker linker = Linker.nativeLinker();
569             SymbolLookup stdlib = linker.defaultLookup();
570             MethodHandle strlen = linker.downcallHandle(
571                     stdlib.find("strlen").orElseThrow(),
572                     FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
573             );
574 
575             try (Arena arena = Arena.ofConfined()) {
576                 MemorySegment cString = arena.allocateFrom("Hello");
577                 long len = (long) strlen.invokeExact(cString); // 5
578             }
579 
580         }
581     }
582 
583     static class PaddingLayoutSnippets {
584     }
585 
586     static class SegmentAllocatorSnippets {
587         void prefixAllocator() {
588             MemorySegment segment = null; //...
589             SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size);
590         }
591 
592     }
593 
594     static class SequenceLayoutSnippets {
595         void header() {
596             MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
597 
598             MemoryLayout.structLayout(
599                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
600                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
601                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
602 
603         }
604 
605         void reshape() {
606             var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
607             var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT));
608 
609             var reshapeSeqImplicit1 = seq.reshape(-1, 6);
610             var reshapeSeqImplicit2 = seq.reshape(2, -1);
611 
612         }
613 
614         void flatten() {
615             var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
616             var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT);
617         }
618 
619     }
620 
621     static class StructLayoutSnippets {
622     }
623 
624     static class SymbolLookupSnippets {
625 
626         void header() {
627             try (Arena arena = Arena.ofConfined()) {
628                 SymbolLookup libGL = libraryLookup("libGL.so", arena); // libGL.so loaded here
629                 MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
630                 // ...
631             } //  libGL.so unloaded here
632 
633             System.loadLibrary("GL"); // libGL.so loaded here
634             // ...
635             SymbolLookup libGL = loaderLookup();
636             MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
637 
638 
639             Arena arena = Arena.ofAuto();
640 
641 
642             libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
643             loaderLookup().find("glGetString").isPresent(); // false
644 
645             libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
646             loaderLookup().find("glGetString").isPresent(); // false
647 
648             Linker nativeLinker = Linker.nativeLinker();
649             SymbolLookup stdlib = nativeLinker.defaultLookup();
650             MemorySegment malloc = stdlib.find("malloc").orElseThrow();
651         }
652 
653     }
654 
655     static class UnionLayoutSnippets {
656     }
657 
658     static class ValueLayoutSnippets {
659 
660         void statics() {
661             ADDRESS.withByteAlignment(1);
662             JAVA_CHAR.withByteAlignment(1);
663             JAVA_SHORT.withByteAlignment(1);
664             JAVA_INT.withByteAlignment(1);
665             JAVA_LONG.withByteAlignment(1);
666             JAVA_FLOAT.withByteAlignment(1);
667             JAVA_DOUBLE.withByteAlignment(1);
668         }
669 
670     }
671 
672 }