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 }