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.allocateArray(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(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.allocateUtf8String("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.allocateArray(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.allocateUtf8String("%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);
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(1L); // 8
355             long offset2 = (long) offsetHandle.invokeExact(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 = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT);
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                 VarHandle intHandle = ValueLayout.JAVA_INT.arrayElementVarHandle();
412                 int value = (int) intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12
413             }
414 
415             {
416                 Arena arena = Arena.ofConfined();
417                 MemorySegment segment = arena.allocate(100);
418                 MemorySegment slice = segment.asSlice(50, 10);
419                 slice.get(ValueLayout.JAVA_INT, 20); // Out of bounds!
420                 arena.close();
421                 slice.get(ValueLayout.JAVA_INT, 0); // Already closed!
422             }
423 
424 
425             {
426                 try (Arena arena = Arena.ofShared()) {
427                     SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
428                     MemorySegment segment = arena.allocate(SEQUENCE_LAYOUT);
429                     int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
430                             .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
431                             .sum();
432                 }
433             }
434 
435             {
436                 MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
437                 byteSegment.get(ValueLayout.JAVA_INT, 0); // fails: layout alignment is 4, segment max alignment is 1
438             }
439 
440             {
441                 MemorySegment longSegment = MemorySegment.ofArray(new long[10]);
442                 longSegment.get(ValueLayout.JAVA_INT, 0); // ok: layout alignment is 4, segment max alignment is 8
443             }
444 
445             {
446                 MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]);
447                 byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: layout alignment is 1, segment max alignment is 1
448             }
449 
450             {
451                 MemorySegment segment = null;
452                 long offset = 42;
453 
454                 MemorySegment z = segment.get(ValueLayout.ADDRESS, offset);   // size = 0
455                 MemorySegment ptr = z.reinterpret(16);                // size = 16
456                 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);        // ok
457             }
458 
459             {
460                 MemorySegment segment = null;
461                 long offset = 42;
462 
463                 MemorySegment ptr = null;
464                 try (Arena arena = Arena.ofConfined()) {
465                     MemorySegment z = segment.get(ValueLayout.ADDRESS, offset);   // size = 0, scope = always alive
466                     ptr = z.reinterpret(16, arena, null);          // size = 4, scope = arena.scope()
467                     int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);        // ok
468                 }
469                 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);            // throws IllegalStateException
470             }
471 
472             {
473                 MemorySegment segment = null;
474                 long offset = 42;
475 
476                 AddressLayout intArrPtrLayout = ValueLayout.ADDRESS.withTargetLayout(
477                         MemoryLayout.sequenceLayout(4, ValueLayout.JAVA_INT)); // layout for int (*ptr)[4]
478                 MemorySegment ptr = segment.get(intArrPtrLayout, offset);                  // size = 16
479                 int x = ptr.getAtIndex(ValueLayout.JAVA_INT, 3);                     // ok
480             }
481 
482 
483         }
484 
485         boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) {
486             return ((segment.address() + offset) % layout.byteAlignment()) == 0;
487         }
488 
489         void elements() {
490             MemorySegment segment = null;
491             MemoryLayout elementLayout = JAVA_INT;
492 
493             StreamSupport.stream(segment.spliterator(elementLayout), false);
494         }
495 
496         void asSlice() {
497             MemorySegment segment = null;
498             long offset = 42;
499             MemoryLayout layout = JAVA_INT;
500 
501             segment.asSlice(offset, layout.byteSize(), 1);
502 
503             segment.asSlice(offset, layout.byteSize(), layout.byteAlignment());
504 
505             segment.asSlice(offset, segment.byteSize() - offset);
506 
507         }
508 
509         void reinterpret() {
510             MemorySegment segment = null;
511 
512             MemorySegment cleanupSegment = MemorySegment.ofAddress(segment.address());
513 
514         }
515 
516         void segmentOffset() {
517             MemorySegment segment = null;
518             MemorySegment other = null;
519 
520             long offset = other.address() - segment.address();
521         }
522 
523         void fill() {
524             MemorySegment segment = null;
525             byte value = 42;
526 
527             var byteHandle = MemoryLayout.sequenceLayout(ValueLayout.JAVA_BYTE)
528                     .varHandle(MemoryLayout.PathElement.sequenceElement());
529             for (long l = 0; l < segment.byteSize(); l++) {
530                 byteHandle.set(segment.address(), l, value);
531             }
532         }
533 
534         void copyFrom() {
535             MemorySegment src = null;
536             MemorySegment dst = null;
537 
538             // MemorySegment.copy(src, 0, this, 0, src.byteSize());
539             MemorySegment.copy(src, 0, dst, 0, src.byteSize());
540         }
541 
542         void copy() {
543             MemorySegment srcSegment = null;
544             long srcOffset = 42;
545             MemorySegment dstSegment = null;
546             long dstOffset = 13;
547             long bytes = 3;
548 
549             MemorySegment.copy(srcSegment, ValueLayout.JAVA_BYTE, srcOffset, dstSegment, ValueLayout.JAVA_BYTE, dstOffset, bytes);
550         }
551 
552 
553     }
554 
555     static class PackageInfoSnippets {
556 
557         void header() throws Throwable {
558             try (Arena arena = Arena.ofConfined()) {
559                 MemorySegment segment = arena.allocate(10 * 4);
560                 for (int i = 0; i < 10; i++) {
561                     segment.setAtIndex(ValueLayout.JAVA_INT, i, i);
562                 }
563             }
564 
565             Linker linker = Linker.nativeLinker();
566             SymbolLookup stdlib = linker.defaultLookup();
567             MethodHandle strlen = linker.downcallHandle(
568                     stdlib.find("strlen").orElseThrow(),
569                     FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
570             );
571 
572             try (Arena arena = Arena.ofConfined()) {
573                 MemorySegment cString = arena.allocateUtf8String("Hello");
574                 long len = (long) strlen.invokeExact(cString); // 5
575             }
576 
577         }
578     }
579 
580     static class PaddingLayoutSnippets {
581     }
582 
583     static class SegmentAllocatorSnippets {
584         void prefixAllocator() {
585             MemorySegment segment = null; //...
586             SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size);
587         }
588 
589     }
590 
591     static class SequenceLayoutSnippets {
592         void header() {
593             MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
594 
595             MemoryLayout.structLayout(
596                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
597                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN),
598                     ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN));
599 
600         }
601 
602         void reshape() {
603             var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
604             var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT));
605 
606             var reshapeSeqImplicit1 = seq.reshape(-1, 6);
607             var reshapeSeqImplicit2 = seq.reshape(2, -1);
608 
609         }
610 
611         void flatten() {
612             var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT));
613             var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT);
614         }
615 
616     }
617 
618     static class StructLayoutSnippets {
619     }
620 
621     static class SymbolLookupSnippets {
622 
623         void header() {
624             try (Arena arena = Arena.ofConfined()) {
625                 SymbolLookup libGL = libraryLookup("libGL.so", arena); // libGL.so loaded here
626                 MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
627                 // ...
628             } //  libGL.so unloaded here
629 
630             System.loadLibrary("GL"); // libGL.so loaded here
631             // ...
632             SymbolLookup libGL = loaderLookup();
633             MemorySegment glGetString = libGL.find("glGetString").orElseThrow();
634 
635 
636             Arena arena = Arena.ofAuto();
637 
638 
639             libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
640             loaderLookup().find("glGetString").isPresent(); // false
641 
642             libraryLookup("libGL.so", arena).find("glGetString").isPresent(); // true
643             loaderLookup().find("glGetString").isPresent(); // false
644 
645             Linker nativeLinker = Linker.nativeLinker();
646             SymbolLookup stdlib = nativeLinker.defaultLookup();
647             MemorySegment malloc = stdlib.find("malloc").orElseThrow();
648         }
649 
650     }
651 
652     static class UnionLayoutSnippets {
653     }
654 
655     static class ValueLayoutSnippets {
656 
657         void arrayElementVarHandle() {
658             VarHandle arrayHandle = ValueLayout.JAVA_INT.arrayElementVarHandle(10, 20);
659 
660             SequenceLayout arrayLayout = MemoryLayout.sequenceLayout(
661                     MemoryLayout.sequenceLayout(10,
662                             MemoryLayout.sequenceLayout(20, ValueLayout.JAVA_INT)));
663 
664             int value1 = (int) arrayHandle.get(10, 2, 4); // ok, accessed offset = 8176
665             int value2 = (int) arrayHandle.get(0, 0, 30); // out of bounds value for z
666         }
667 
668         void statics() {
669             ADDRESS.withByteAlignment(1);
670             JAVA_CHAR.withByteAlignment(1);
671             JAVA_SHORT.withByteAlignment(1);
672             JAVA_INT.withByteAlignment(1);
673             JAVA_LONG.withByteAlignment(1);
674             JAVA_FLOAT.withByteAlignment(1);
675             JAVA_DOUBLE.withByteAlignment(1);
676         }
677 
678     }
679 
680 }