1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.util.internal;
17
18 import io.netty.util.internal.logging.InternalLogger;
19 import io.netty.util.internal.logging.InternalLoggerFactory;
20 import jdk.jfr.FlightRecorder;
21 import org.jctools.queues.MpmcArrayQueue;
22 import org.jctools.queues.MpscArrayQueue;
23 import org.jctools.queues.MpscChunkedArrayQueue;
24 import org.jctools.queues.MpscUnboundedArrayQueue;
25 import org.jctools.queues.SpscLinkedQueue;
26 import org.jctools.queues.atomic.MpmcAtomicArrayQueue;
27 import org.jctools.queues.atomic.MpscAtomicArrayQueue;
28 import org.jctools.queues.atomic.MpscChunkedAtomicArrayQueue;
29 import org.jctools.queues.atomic.MpscUnboundedAtomicArrayQueue;
30 import org.jctools.queues.atomic.SpscLinkedAtomicQueue;
31 import org.jctools.queues.atomic.unpadded.MpscAtomicUnpaddedArrayQueue;
32 import org.jctools.queues.unpadded.MpscUnpaddedArrayQueue;
33 import org.jctools.util.Pow2;
34 import org.jctools.util.UnsafeAccess;
35
36 import java.io.BufferedReader;
37 import java.io.File;
38 import java.io.IOException;
39 import java.io.InputStreamReader;
40 import java.lang.invoke.MethodHandle;
41 import java.lang.invoke.MethodHandles;
42 import java.lang.invoke.VarHandle;
43 import java.lang.reflect.Field;
44 import java.nio.ByteBuffer;
45 import java.nio.ByteOrder;
46 import java.nio.charset.StandardCharsets;
47 import java.nio.file.Files;
48 import java.nio.file.Path;
49 import java.nio.file.Paths;
50 import java.security.AccessController;
51 import java.security.PrivilegedAction;
52 import java.util.Arrays;
53 import java.util.Collections;
54 import java.util.Deque;
55 import java.util.LinkedHashSet;
56 import java.util.List;
57 import java.util.Locale;
58 import java.util.Map;
59 import java.util.Queue;
60 import java.util.Random;
61 import java.util.Set;
62 import java.util.SplittableRandom;
63 import java.util.concurrent.ConcurrentHashMap;
64 import java.util.concurrent.ConcurrentLinkedDeque;
65 import java.util.concurrent.ConcurrentMap;
66 import java.util.concurrent.ThreadLocalRandom;
67 import java.util.concurrent.atomic.AtomicLong;
68 import java.util.regex.Matcher;
69 import java.util.regex.Pattern;
70
71 import static io.netty.util.internal.PlatformDependent0.HASH_CODE_ASCII_SEED;
72 import static io.netty.util.internal.PlatformDependent0.HASH_CODE_C1;
73 import static io.netty.util.internal.PlatformDependent0.HASH_CODE_C2;
74 import static io.netty.util.internal.PlatformDependent0.hashCodeAsciiSanitize;
75 import static io.netty.util.internal.PlatformDependent0.unalignedAccess;
76 import static java.lang.Math.max;
77 import static java.lang.Math.min;
78 import static java.lang.invoke.MethodType.methodType;
79
80
81
82
83
84
85
86
87
88 public final class PlatformDependent {
89
90 private static final InternalLogger logger = InternalLoggerFactory.getInstance(PlatformDependent.class);
91
92 private static Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN;
93 private static final boolean MAYBE_SUPER_USER;
94
95 private static final boolean CAN_ENABLE_TCP_NODELAY_BY_DEFAULT = !isAndroid();
96
97 private static final Throwable UNSAFE_UNAVAILABILITY_CAUSE = unsafeUnavailabilityCause0();
98 private static final boolean DIRECT_BUFFER_PREFERRED;
99 private static final boolean EXPLICIT_NO_PREFER_DIRECT;
100 private static final long MAX_DIRECT_MEMORY = estimateMaxDirectMemory();
101
102 private static final int MPSC_CHUNK_SIZE = 1024;
103 private static final int MIN_MAX_MPSC_CAPACITY = MPSC_CHUNK_SIZE * 2;
104 private static final int MAX_ALLOWED_MPSC_CAPACITY = Pow2.MAX_POW2;
105
106 private static final long BYTE_ARRAY_BASE_OFFSET = byteArrayBaseOffset0();
107
108 private static final File TMPDIR = tmpdir0();
109
110 private static final int BIT_MODE = bitMode0();
111 private static final String NORMALIZED_ARCH = normalizeArch(SystemPropertyUtil.get("os.arch", ""));
112 private static final String NORMALIZED_OS = normalizeOs(SystemPropertyUtil.get("os.name", ""));
113
114 private static final Set<String> LINUX_OS_CLASSIFIERS;
115
116 private static final boolean IS_WINDOWS = isWindows0();
117 private static final boolean IS_OSX = isOsx0();
118 private static final boolean IS_J9_JVM = isJ9Jvm0();
119 private static final boolean IS_IVKVM_DOT_NET = isIkvmDotNet0();
120
121 private static final int ADDRESS_SIZE = addressSize0();
122 private static final AtomicLong DIRECT_MEMORY_COUNTER;
123 private static final long DIRECT_MEMORY_LIMIT;
124 private static final Cleaner CLEANER;
125 private static final Cleaner LEGACY_CLEANER;
126 private static final boolean HAS_ALLOCATE_UNINIT_ARRAY;
127 private static final String LINUX_ID_PREFIX = "ID=";
128 private static final String LINUX_ID_LIKE_PREFIX = "ID_LIKE=";
129 public static final boolean BIG_ENDIAN_NATIVE_ORDER = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN;
130 private static final boolean IGNORE_EXPENSIVE_CLEAN =
131 SystemPropertyUtil.getBoolean("io.netty.ignoreExpensiveClean", false);
132
133 private static final boolean JFR;
134 private static final boolean VAR_HANDLE;
135
136 private static final Cleaner NOOP = new Cleaner() {
137 @Override
138 public CleanableDirectBuffer allocate(int capacity) {
139 return new CleanableDirectBuffer() {
140 private final ByteBuffer byteBuffer = ByteBuffer.allocateDirect(capacity);
141
142 @Override
143 public ByteBuffer buffer() {
144 return byteBuffer;
145 }
146
147 @Override
148 public void clean() {
149
150 }
151
152 @Override
153 public boolean hasMemoryAddress() {
154 return hasDirectByteBufferAddress(byteBuffer);
155 }
156
157 @Override
158 public long memoryAddress() {
159 return directBufferAddress(byteBuffer);
160 }
161 };
162 }
163
164 @Override
165 public void freeDirectBuffer(ByteBuffer buffer) {
166
167 }
168
169 @Override
170 public boolean hasExpensiveClean() {
171 return false;
172 }
173 };
174
175 static {
176
177
178
179
180
181
182
183 long maxDirectMemory = SystemPropertyUtil.getLong("io.netty.maxDirectMemory", -1);
184
185
186
187 if (maxDirectMemory == 0) {
188 DIRECT_MEMORY_COUNTER = null;
189 } else if (maxDirectMemory < 0) {
190 maxDirectMemory = MAX_DIRECT_MEMORY;
191 if (maxDirectMemory <= 0) {
192 DIRECT_MEMORY_COUNTER = null;
193 } else {
194 DIRECT_MEMORY_COUNTER = new AtomicLong();
195 }
196 } else {
197 DIRECT_MEMORY_COUNTER = new AtomicLong();
198 }
199 logger.debug("-Dio.netty.maxDirectMemory: {} bytes", maxDirectMemory);
200 DIRECT_MEMORY_LIMIT = maxDirectMemory >= 1 ? maxDirectMemory : MAX_DIRECT_MEMORY;
201 HAS_ALLOCATE_UNINIT_ARRAY = javaVersion() >= 9 && PlatformDependent0.hasAllocateArrayMethod();
202
203 MAYBE_SUPER_USER = maybeSuperUser0();
204
205 if (!isAndroid()) {
206
207
208 if (javaVersion() >= 9) {
209
210 if (CleanerJava9.isSupported()) {
211 LEGACY_CLEANER = new CleanerJava9();
212 } else if (CleanerJava24Linker.isSupported()) {
213
214
215
216
217 LEGACY_CLEANER = new CleanerJava24Linker();
218 } else if (CleanerJava25.isSupported()) {
219
220
221
222 LEGACY_CLEANER = new CleanerJava25();
223 } else {
224 LEGACY_CLEANER = NOOP;
225 }
226 } else {
227 LEGACY_CLEANER = CleanerJava6.isSupported() ? new CleanerJava6() : NOOP;
228 }
229 } else {
230 LEGACY_CLEANER = NOOP;
231 }
232 if (maxDirectMemory != 0 && hasUnsafe() && PlatformDependent0.hasDirectBufferNoCleanerConstructor()) {
233 CLEANER = new DirectCleaner();
234 } else {
235 CLEANER = LEGACY_CLEANER;
236 }
237
238 EXPLICIT_NO_PREFER_DIRECT = SystemPropertyUtil.getBoolean("io.netty.noPreferDirect", false);
239
240 DIRECT_BUFFER_PREFERRED = CLEANER != NOOP
241 && !EXPLICIT_NO_PREFER_DIRECT;
242 if (logger.isDebugEnabled()) {
243 logger.debug("-Dio.netty.noPreferDirect: {}", EXPLICIT_NO_PREFER_DIRECT);
244 }
245
246 logger.debug("-Dio.netty.ignoreExpensiveClean: {}", IGNORE_EXPENSIVE_CLEAN);
247
248
249
250
251
252 if (CLEANER == NOOP && !PlatformDependent0.isExplicitNoUnsafe()) {
253 logger.info(
254 "Your platform does not provide complete low-level API for accessing direct buffers reliably. " +
255 "Unless explicitly requested, heap buffer will always be preferred to avoid potential system " +
256 "instability.");
257 }
258
259 final Set<String> availableClassifiers = new LinkedHashSet<>();
260
261 if (!addPropertyOsClassifiers(availableClassifiers)) {
262 addFilesystemOsClassifiers(availableClassifiers);
263 }
264 LINUX_OS_CLASSIFIERS = Collections.unmodifiableSet(availableClassifiers);
265
266 boolean jfrAvailable;
267 Throwable jfrFailure = null;
268 try {
269
270 jfrAvailable = FlightRecorder.isAvailable();
271 } catch (Throwable t) {
272 jfrFailure = t;
273 jfrAvailable = false;
274 }
275 JFR = SystemPropertyUtil.getBoolean("io.netty.jfr.enabled", jfrAvailable);
276 if (logger.isTraceEnabled() && jfrFailure != null) {
277 logger.debug("-Dio.netty.jfr.enabled: {}", JFR, jfrFailure);
278 } else if (logger.isDebugEnabled()) {
279 logger.debug("-Dio.netty.jfr.enabled: {}", JFR);
280 }
281 VAR_HANDLE = initializeVarHandle();
282 }
283
284 private static boolean initializeVarHandle() {
285 if (isUnaligned() || javaVersion() < 9 ||
286 PlatformDependent0.isNativeImage()) {
287 return false;
288 }
289 boolean varHandleAvailable = false;
290 Throwable varHandleFailure;
291 try {
292 VarHandle.storeStoreFence();
293 varHandleAvailable = VarHandleFactory.isSupported();
294 varHandleFailure = VarHandleFactory.unavailableCause();
295 } catch (Throwable t) {
296
297 varHandleFailure = t;
298 }
299 if (varHandleFailure != null) {
300 logger.debug("java.lang.invoke.VarHandle: unavailable, reason: {}", varHandleFailure.toString());
301 } else {
302 logger.debug("java.lang.invoke.VarHandle: available");
303 }
304 boolean varHandleEnabled = varHandleAvailable &&
305 SystemPropertyUtil.getBoolean("io.netty.varHandle.enabled", varHandleAvailable);
306 if (logger.isTraceEnabled() && varHandleFailure != null) {
307 logger.debug("-Dio.netty.varHandle.enabled: {}", varHandleEnabled, varHandleFailure);
308 } else if (logger.isDebugEnabled()) {
309 logger.debug("-Dio.netty.varHandle.enabled: {}", varHandleEnabled);
310 }
311 return varHandleEnabled;
312 }
313
314
315 static void addFilesystemOsClassifiers(final Set<String> availableClassifiers) {
316 if (processOsReleaseFile("/etc/os-release", availableClassifiers)) {
317 return;
318 }
319 processOsReleaseFile("/usr/lib/os-release", availableClassifiers);
320 }
321
322 private static boolean processOsReleaseFile(String osReleaseFileName, Set<String> availableClassifiers) {
323 Path file = Paths.get(osReleaseFileName);
324 return AccessController.doPrivileged((PrivilegedAction<Boolean>) () -> {
325 try {
326 if (Files.exists(file)) {
327 try (BufferedReader reader = new BufferedReader(new InputStreamReader(
328 new BoundedInputStream(Files.newInputStream(file)), StandardCharsets.UTF_8))) {
329 String line;
330 while ((line = reader.readLine()) != null) {
331 if (line.startsWith(LINUX_ID_PREFIX)) {
332 String id = normalizeOsReleaseVariableValue(
333 line.substring(LINUX_ID_PREFIX.length()));
334 addClassifier(availableClassifiers, id);
335 } else if (line.startsWith(LINUX_ID_LIKE_PREFIX)) {
336 line = normalizeOsReleaseVariableValue(
337 line.substring(LINUX_ID_LIKE_PREFIX.length()));
338 addClassifier(availableClassifiers, line.split(" "));
339 }
340 }
341 } catch (SecurityException e) {
342 logger.debug("Unable to read {}", osReleaseFileName, e);
343 } catch (IOException e) {
344 logger.debug("Error while reading content of {}", osReleaseFileName, e);
345 }
346
347 return true;
348 }
349 } catch (SecurityException e) {
350 logger.debug("Unable to check if {} exists", osReleaseFileName, e);
351 }
352 return false;
353 });
354 }
355
356 static boolean addPropertyOsClassifiers(Set<String> availableClassifiers) {
357
358
359
360
361 String osClassifiersPropertyName = "io.netty.osClassifiers";
362 String osClassifiers = SystemPropertyUtil.get(osClassifiersPropertyName);
363 if (osClassifiers == null) {
364 return false;
365 }
366 if (osClassifiers.isEmpty()) {
367
368 return true;
369 }
370 String[] classifiers = osClassifiers.split(",");
371 if (classifiers.length == 0) {
372 throw new IllegalArgumentException(
373 osClassifiersPropertyName + " property is not empty, but contains no classifiers: "
374 + osClassifiers);
375 }
376
377 if (classifiers.length > 2) {
378 throw new IllegalArgumentException(
379 osClassifiersPropertyName + " property contains more than 2 classifiers: " + osClassifiers);
380 }
381 for (String classifier : classifiers) {
382 addClassifier(availableClassifiers, classifier);
383 }
384 return true;
385 }
386
387 public static long byteArrayBaseOffset() {
388 return BYTE_ARRAY_BASE_OFFSET;
389 }
390
391 public static boolean hasDirectBufferNoCleanerConstructor() {
392 return PlatformDependent0.hasDirectBufferNoCleanerConstructor();
393 }
394
395 public static byte[] allocateUninitializedArray(int size) {
396 return HAS_ALLOCATE_UNINIT_ARRAY ? PlatformDependent0.allocateUninitializedArray(size) : new byte[size];
397 }
398
399
400
401
402 public static boolean isAndroid() {
403 return PlatformDependent0.isAndroid();
404 }
405
406
407
408
409 public static boolean isWindows() {
410 return IS_WINDOWS;
411 }
412
413
414
415
416 public static boolean isOsx() {
417 return IS_OSX;
418 }
419
420
421
422
423
424 public static boolean maybeSuperUser() {
425 return MAYBE_SUPER_USER;
426 }
427
428
429
430
431 public static int javaVersion() {
432 return PlatformDependent0.javaVersion();
433 }
434
435
436
437
438
439 public static boolean isVirtualThread(Thread thread) {
440 return PlatformDependent0.isVirtualThread(thread);
441 }
442
443
444
445
446 public static boolean canEnableTcpNoDelayByDefault() {
447 return CAN_ENABLE_TCP_NODELAY_BY_DEFAULT;
448 }
449
450
451
452
453
454 public static boolean hasUnsafe() {
455 return UNSAFE_UNAVAILABILITY_CAUSE == null;
456 }
457
458
459
460
461 public static Throwable getUnsafeUnavailabilityCause() {
462 return UNSAFE_UNAVAILABILITY_CAUSE;
463 }
464
465
466
467
468
469
470 public static boolean isUnaligned() {
471 return PlatformDependent0.isUnaligned();
472 }
473
474
475
476
477
478 public static boolean directBufferPreferred() {
479 return DIRECT_BUFFER_PREFERRED;
480 }
481
482
483
484
485
486 public static boolean isExplicitNoPreferDirect() {
487 return EXPLICIT_NO_PREFER_DIRECT;
488 }
489
490
491
492
493
494
495 public static boolean canReliabilyFreeDirectBuffers() {
496 return CLEANER != NOOP;
497 }
498
499
500
501
502 public static long maxDirectMemory() {
503 return DIRECT_MEMORY_LIMIT;
504 }
505
506
507
508
509
510
511
512 public static long usedDirectMemory() {
513 return DIRECT_MEMORY_COUNTER != null ? DIRECT_MEMORY_COUNTER.get() : -1;
514 }
515
516
517
518
519 public static File tmpdir() {
520 return TMPDIR;
521 }
522
523
524
525
526 public static int bitMode() {
527 return BIT_MODE;
528 }
529
530
531
532
533
534 public static int addressSize() {
535 return ADDRESS_SIZE;
536 }
537
538 public static long allocateMemory(long size) {
539 return PlatformDependent0.allocateMemory(size);
540 }
541
542 public static void freeMemory(long address) {
543 PlatformDependent0.freeMemory(address);
544 }
545
546 public static long reallocateMemory(long address, long newSize) {
547 return PlatformDependent0.reallocateMemory(address, newSize);
548 }
549
550
551
552
553 public static void throwException(Throwable t) {
554 PlatformDependent0.throwException(t);
555 }
556
557
558
559
560
561 @Deprecated
562 public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap() {
563 return new ConcurrentHashMap<>();
564 }
565
566
567
568
569
570 @Deprecated
571 public static LongCounter newLongCounter() {
572 return new LongAdderCounter();
573 }
574
575
576
577
578
579 @Deprecated
580 public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(int initialCapacity) {
581 return new ConcurrentHashMap<>(initialCapacity);
582 }
583
584
585
586
587
588 @Deprecated
589 public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(int initialCapacity, float loadFactor) {
590 return new ConcurrentHashMap<>(initialCapacity, loadFactor);
591 }
592
593
594
595
596
597 @Deprecated
598 public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(
599 int initialCapacity, float loadFactor, int concurrencyLevel) {
600 return new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
601 }
602
603
604
605
606
607 @Deprecated
608 public static <K, V> ConcurrentMap<K, V> newConcurrentHashMap(Map<? extends K, ? extends V> map) {
609 return new ConcurrentHashMap<>(map);
610 }
611
612
613
614
615
616
617 public static CleanableDirectBuffer allocateDirect(int capacity) {
618 return allocateDirect(capacity, false);
619 }
620
621
622
623
624
625
626
627
628
629
630 public static CleanableDirectBuffer allocateDirect(int capacity, boolean permitExpensiveClean) {
631 if (!IGNORE_EXPENSIVE_CLEAN && !permitExpensiveClean && CLEANER.hasExpensiveClean()) {
632 return NOOP.allocate(capacity);
633 }
634 return CLEANER.allocate(capacity);
635 }
636
637
638
639
640
641
642
643
644
645 public static CleanableDirectBuffer reallocateDirect(CleanableDirectBuffer buffer, int newCapacity) {
646 return CLEANER.reallocate(buffer, newCapacity);
647 }
648
649
650
651
652
653
654
655 @Deprecated
656 public static void freeDirectBuffer(ByteBuffer buffer) {
657 LEGACY_CLEANER.freeDirectBuffer(buffer);
658 }
659
660
661
662
663
664
665
666 public static boolean hasDirectByteBufferAddress(ByteBuffer buffer) {
667 return PlatformDependent0.hasDirectByteBufferAddress(buffer);
668 }
669
670
671
672
673
674
675 public static long directBufferAddress(ByteBuffer buffer) {
676 return PlatformDependent0.directBufferAddress(buffer);
677 }
678
679 public static ByteBuffer directBuffer(long memoryAddress, int size) {
680 if (PlatformDependent0.hasDirectBufferNoCleanerConstructor()) {
681 return PlatformDependent0.newDirectBuffer(memoryAddress, size);
682 }
683 throw new UnsupportedOperationException(
684 "sun.misc.Unsafe or java.nio.DirectByteBuffer.<init>(long, int) not available");
685 }
686
687 public static boolean hasVarHandle() {
688 return VAR_HANDLE;
689 }
690
691
692
693
694
695
696
697
698
699 public static boolean useVarHandleForMultiByteAccess() {
700 return !isUnaligned() && VAR_HANDLE;
701 }
702
703
704
705
706
707 public static boolean canUnalignedAccess() {
708 return isUnaligned() || VAR_HANDLE;
709 }
710
711 public static VarHandle findVarHandleOfIntField(MethodHandles.Lookup lookup, Class<?> type, String fieldName) {
712 if (VAR_HANDLE) {
713 return VarHandleFactory.privateFindVarHandle(lookup, type, fieldName, int.class);
714 }
715 return null;
716 }
717
718 public static VarHandle intBeArrayView() {
719 if (VAR_HANDLE) {
720 return VarHandleFactory.intBeArrayView();
721 }
722 return null;
723 }
724
725 public static VarHandle intLeArrayView() {
726 if (VAR_HANDLE) {
727 return VarHandleFactory.intLeArrayView();
728 }
729 return null;
730 }
731
732 public static VarHandle longBeArrayView() {
733 if (VAR_HANDLE) {
734 return VarHandleFactory.longBeArrayView();
735 }
736 return null;
737 }
738
739 public static VarHandle longLeArrayView() {
740 if (VAR_HANDLE) {
741 return VarHandleFactory.longLeArrayView();
742 }
743 return null;
744 }
745
746 public static VarHandle shortBeArrayView() {
747 if (VAR_HANDLE) {
748 return VarHandleFactory.shortBeArrayView();
749 }
750 return null;
751 }
752
753 public static VarHandle shortLeArrayView() {
754 if (VAR_HANDLE) {
755 return VarHandleFactory.shortLeArrayView();
756 }
757 return null;
758 }
759
760 public static VarHandle longBeByteBufferView() {
761 if (VAR_HANDLE) {
762 return VarHandleFactory.longBeByteBufferView();
763 }
764 return null;
765 }
766
767 public static VarHandle longLeByteBufferView() {
768 if (VAR_HANDLE) {
769 return VarHandleFactory.longLeByteBufferView();
770 }
771 return null;
772 }
773
774 public static VarHandle intBeByteBufferView() {
775 if (VAR_HANDLE) {
776 return VarHandleFactory.intBeByteBufferView();
777 }
778 return null;
779 }
780
781 public static VarHandle intLeByteBufferView() {
782 if (VAR_HANDLE) {
783 return VarHandleFactory.intLeByteBufferView();
784 }
785 return null;
786 }
787
788 public static VarHandle shortBeByteBufferView() {
789 if (VAR_HANDLE) {
790 return VarHandleFactory.shortBeByteBufferView();
791 }
792 return null;
793 }
794
795 public static VarHandle shortLeByteBufferView() {
796 if (VAR_HANDLE) {
797 return VarHandleFactory.shortLeByteBufferView();
798 }
799 return null;
800 }
801
802 public static Object getObject(Object object, long fieldOffset) {
803 return PlatformDependent0.getObject(object, fieldOffset);
804 }
805
806 public static int getVolatileInt(Object object, long fieldOffset) {
807 return PlatformDependent0.getIntVolatile(object, fieldOffset);
808 }
809
810 public static int getInt(Object object, long fieldOffset) {
811 return PlatformDependent0.getInt(object, fieldOffset);
812 }
813
814 public static void putOrderedInt(Object object, long fieldOffset, int value) {
815 PlatformDependent0.putOrderedInt(object, fieldOffset, value);
816 }
817
818 public static int getAndAddInt(Object object, long fieldOffset, int delta) {
819 return PlatformDependent0.getAndAddInt(object, fieldOffset, delta);
820 }
821
822 public static boolean compareAndSwapInt(Object object, long fieldOffset, int expected, int value) {
823 return PlatformDependent0.compareAndSwapInt(object, fieldOffset, expected, value);
824 }
825
826 static void safeConstructPutInt(Object object, long fieldOffset, int value) {
827 PlatformDependent0.safeConstructPutInt(object, fieldOffset, value);
828 }
829
830 public static byte getByte(long address) {
831 return PlatformDependent0.getByte(address);
832 }
833
834 public static short getShort(long address) {
835 return PlatformDependent0.getShort(address);
836 }
837
838 public static int getInt(long address) {
839 return PlatformDependent0.getInt(address);
840 }
841
842 public static long getLong(long address) {
843 return PlatformDependent0.getLong(address);
844 }
845
846 public static byte getByte(byte[] data, int index) {
847 return hasUnsafe() ? PlatformDependent0.getByte(data, index) : data[index];
848 }
849
850 public static byte getByte(byte[] data, long index) {
851 return hasUnsafe() ? PlatformDependent0.getByte(data, index) : data[toIntExact(index)];
852 }
853
854 public static short getShort(byte[] data, int index) {
855 return hasUnsafe() ? PlatformDependent0.getShort(data, index) : data[index];
856 }
857
858 public static int getInt(byte[] data, int index) {
859 return hasUnsafe() ? PlatformDependent0.getInt(data, index) : data[index];
860 }
861
862 public static int getInt(int[] data, long index) {
863 return hasUnsafe() ? PlatformDependent0.getInt(data, index) : data[toIntExact(index)];
864 }
865
866 public static long getLong(byte[] data, int index) {
867 return hasUnsafe() ? PlatformDependent0.getLong(data, index) : data[index];
868 }
869
870 public static long getLong(long[] data, long index) {
871 return hasUnsafe() ? PlatformDependent0.getLong(data, index) : data[toIntExact(index)];
872 }
873
874 private static int toIntExact(long value) {
875 return Math.toIntExact(value);
876 }
877
878 private static long getLongSafe(byte[] bytes, int offset) {
879 if (BIG_ENDIAN_NATIVE_ORDER) {
880 return (long) bytes[offset] << 56 |
881 ((long) bytes[offset + 1] & 0xff) << 48 |
882 ((long) bytes[offset + 2] & 0xff) << 40 |
883 ((long) bytes[offset + 3] & 0xff) << 32 |
884 ((long) bytes[offset + 4] & 0xff) << 24 |
885 ((long) bytes[offset + 5] & 0xff) << 16 |
886 ((long) bytes[offset + 6] & 0xff) << 8 |
887 (long) bytes[offset + 7] & 0xff;
888 }
889 return (long) bytes[offset] & 0xff |
890 ((long) bytes[offset + 1] & 0xff) << 8 |
891 ((long) bytes[offset + 2] & 0xff) << 16 |
892 ((long) bytes[offset + 3] & 0xff) << 24 |
893 ((long) bytes[offset + 4] & 0xff) << 32 |
894 ((long) bytes[offset + 5] & 0xff) << 40 |
895 ((long) bytes[offset + 6] & 0xff) << 48 |
896 (long) bytes[offset + 7] << 56;
897 }
898
899 private static int getIntSafe(byte[] bytes, int offset) {
900 if (BIG_ENDIAN_NATIVE_ORDER) {
901 return bytes[offset] << 24 |
902 (bytes[offset + 1] & 0xff) << 16 |
903 (bytes[offset + 2] & 0xff) << 8 |
904 bytes[offset + 3] & 0xff;
905 }
906 return bytes[offset] & 0xff |
907 (bytes[offset + 1] & 0xff) << 8 |
908 (bytes[offset + 2] & 0xff) << 16 |
909 bytes[offset + 3] << 24;
910 }
911
912 private static short getShortSafe(byte[] bytes, int offset) {
913 if (BIG_ENDIAN_NATIVE_ORDER) {
914 return (short) (bytes[offset] << 8 | (bytes[offset + 1] & 0xff));
915 }
916 return (short) (bytes[offset] & 0xff | (bytes[offset + 1] << 8));
917 }
918
919
920
921
922 private static int hashCodeAsciiCompute(CharSequence value, int offset, int hash) {
923 if (BIG_ENDIAN_NATIVE_ORDER) {
924 return hash * HASH_CODE_C1 +
925
926 hashCodeAsciiSanitizeInt(value, offset + 4) * HASH_CODE_C2 +
927
928 hashCodeAsciiSanitizeInt(value, offset);
929 }
930 return hash * HASH_CODE_C1 +
931
932 hashCodeAsciiSanitizeInt(value, offset) * HASH_CODE_C2 +
933
934 hashCodeAsciiSanitizeInt(value, offset + 4);
935 }
936
937
938
939
940 private static int hashCodeAsciiSanitizeInt(CharSequence value, int offset) {
941 if (BIG_ENDIAN_NATIVE_ORDER) {
942
943 return (value.charAt(offset + 3) & 0x1f) |
944 (value.charAt(offset + 2) & 0x1f) << 8 |
945 (value.charAt(offset + 1) & 0x1f) << 16 |
946 (value.charAt(offset) & 0x1f) << 24;
947 }
948 return (value.charAt(offset + 3) & 0x1f) << 24 |
949 (value.charAt(offset + 2) & 0x1f) << 16 |
950 (value.charAt(offset + 1) & 0x1f) << 8 |
951 (value.charAt(offset) & 0x1f);
952 }
953
954
955
956
957 private static int hashCodeAsciiSanitizeShort(CharSequence value, int offset) {
958 if (BIG_ENDIAN_NATIVE_ORDER) {
959
960 return (value.charAt(offset + 1) & 0x1f) |
961 (value.charAt(offset) & 0x1f) << 8;
962 }
963 return (value.charAt(offset + 1) & 0x1f) << 8 |
964 (value.charAt(offset) & 0x1f);
965 }
966
967
968
969
970 private static int hashCodeAsciiSanitizeByte(char value) {
971 return value & 0x1f;
972 }
973
974 public static void putByte(long address, byte value) {
975 PlatformDependent0.putByte(address, value);
976 }
977
978 public static void putShort(long address, short value) {
979 PlatformDependent0.putShort(address, value);
980 }
981
982 public static void putInt(long address, int value) {
983 PlatformDependent0.putInt(address, value);
984 }
985
986 public static void putLong(long address, long value) {
987 PlatformDependent0.putLong(address, value);
988 }
989
990 public static void putByte(byte[] data, int index, byte value) {
991 PlatformDependent0.putByte(data, index, value);
992 }
993
994 public static void putByte(Object data, long offset, byte value) {
995 PlatformDependent0.putByte(data, offset, value);
996 }
997
998 public static void putShort(byte[] data, int index, short value) {
999 PlatformDependent0.putShort(data, index, value);
1000 }
1001
1002 public static void putInt(byte[] data, int index, int value) {
1003 PlatformDependent0.putInt(data, index, value);
1004 }
1005
1006 public static void putLong(byte[] data, int index, long value) {
1007 PlatformDependent0.putLong(data, index, value);
1008 }
1009
1010 public static void putObject(Object o, long offset, Object x) {
1011 PlatformDependent0.putObject(o, offset, x);
1012 }
1013
1014 public static long objectFieldOffset(Field field) {
1015 return PlatformDependent0.objectFieldOffset(field);
1016 }
1017
1018 public static void copyMemory(long srcAddr, long dstAddr, long length) {
1019 PlatformDependent0.copyMemory(srcAddr, dstAddr, length);
1020 }
1021
1022 public static void copyMemory(byte[] src, int srcIndex, long dstAddr, long length) {
1023 PlatformDependent0.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, dstAddr, length);
1024 }
1025
1026 public static void copyMemory(byte[] src, int srcIndex, byte[] dst, int dstIndex, long length) {
1027 PlatformDependent0.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex,
1028 dst, BYTE_ARRAY_BASE_OFFSET + dstIndex, length);
1029 }
1030
1031 public static void copyMemory(long srcAddr, byte[] dst, int dstIndex, long length) {
1032 PlatformDependent0.copyMemory(null, srcAddr, dst, BYTE_ARRAY_BASE_OFFSET + dstIndex, length);
1033 }
1034
1035 public static void setMemory(byte[] dst, int dstIndex, long bytes, byte value) {
1036 PlatformDependent0.setMemory(dst, BYTE_ARRAY_BASE_OFFSET + dstIndex, bytes, value);
1037 }
1038
1039 public static void setMemory(long address, long bytes, byte value) {
1040 PlatformDependent0.setMemory(address, bytes, value);
1041 }
1042
1043 public static boolean hasAlignDirectByteBuffer() {
1044 return hasUnsafe() || PlatformDependent0.hasAlignSliceMethod();
1045 }
1046
1047 public static ByteBuffer alignDirectBuffer(ByteBuffer buffer, int alignment) {
1048 if (!buffer.isDirect()) {
1049 throw new IllegalArgumentException("Cannot get aligned slice of non-direct byte buffer.");
1050 }
1051 if (PlatformDependent0.hasAlignSliceMethod()) {
1052 return PlatformDependent0.alignSlice(buffer, alignment);
1053 }
1054 if (hasUnsafe()) {
1055 long address = directBufferAddress(buffer);
1056 long aligned = align(address, alignment);
1057 buffer.position((int) (aligned - address));
1058 return buffer.slice();
1059 }
1060
1061 throw new UnsupportedOperationException("Cannot align direct buffer. " +
1062 "Needs either Unsafe or ByteBuffer.alignSlice method available.");
1063 }
1064
1065 public static long align(long value, int alignment) {
1066 return Pow2.align(value, alignment);
1067 }
1068
1069 public static ByteBuffer offsetSlice(ByteBuffer buffer, int index, int length) {
1070 if (PlatformDependent0.hasOffsetSliceMethod()) {
1071 return PlatformDependent0.offsetSlice(buffer, index, length);
1072 } else {
1073 return ((ByteBuffer) buffer.duplicate().clear().position(index).limit(index + length)).slice();
1074 }
1075 }
1076
1077 public static ByteBuffer absolutePut(ByteBuffer dst, int dstOffset, byte[] src, int srcOffset, int length) {
1078 if (PlatformDependent0.hasAbsolutePutArrayMethod()) {
1079 return PlatformDependent0.absolutePut(dst, dstOffset, src, srcOffset, length);
1080 } else {
1081 ByteBuffer tmp = (ByteBuffer) dst.duplicate().clear().position(dstOffset).limit(dstOffset + length);
1082 tmp.put(ByteBuffer.wrap(src, srcOffset, length));
1083 return dst;
1084 }
1085 }
1086
1087 public static ByteBuffer absolutePut(ByteBuffer dst, int dstOffset, ByteBuffer src, int srcOffset, int length) {
1088 if (PlatformDependent0.hasAbsolutePutBufferMethod()) {
1089 return PlatformDependent0.absolutePut(dst, dstOffset, src, srcOffset, length);
1090 } else {
1091 ByteBuffer a = (ByteBuffer) dst.duplicate().clear().position(dstOffset).limit(dstOffset + length);
1092 ByteBuffer b = (ByteBuffer) src.duplicate().clear().position(srcOffset).limit(srcOffset + length);
1093 a.put(b);
1094 return dst;
1095 }
1096 }
1097
1098 static void incrementMemoryCounter(int capacity) {
1099 if (DIRECT_MEMORY_COUNTER != null) {
1100 long newUsedMemory = DIRECT_MEMORY_COUNTER.addAndGet(capacity);
1101 if (newUsedMemory > DIRECT_MEMORY_LIMIT) {
1102 DIRECT_MEMORY_COUNTER.addAndGet(-capacity);
1103 throw new OutOfDirectMemoryError("failed to allocate " + capacity
1104 + " byte(s) of direct memory (used: " + (newUsedMemory - capacity)
1105 + ", max: " + DIRECT_MEMORY_LIMIT + ')');
1106 }
1107 }
1108 }
1109
1110 static void decrementMemoryCounter(int capacity) {
1111 if (DIRECT_MEMORY_COUNTER != null) {
1112 long usedMemory = DIRECT_MEMORY_COUNTER.addAndGet(-capacity);
1113 assert usedMemory >= 0;
1114 }
1115 }
1116
1117 public static boolean useDirectBufferNoCleaner() {
1118 return CLEANER instanceof DirectCleaner;
1119 }
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132 public static boolean equals(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
1133 if (javaVersion() > 8 && (startPos2 | startPos1 | (bytes1.length - length) | bytes2.length - length) == 0) {
1134 return Arrays.equals(bytes1, bytes2);
1135 }
1136 return !hasUnsafe() || !unalignedAccess() ?
1137 equalsSafe(bytes1, startPos1, bytes2, startPos2, length) :
1138 PlatformDependent0.equals(bytes1, startPos1, bytes2, startPos2, length);
1139 }
1140
1141
1142
1143
1144
1145
1146
1147
1148 public static boolean isZero(byte[] bytes, int startPos, int length) {
1149 return !hasUnsafe() || !unalignedAccess() ?
1150 isZeroSafe(bytes, startPos, length) :
1151 PlatformDependent0.isZero(bytes, startPos, length);
1152 }
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175 public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
1176 return !hasUnsafe() || !unalignedAccess() ?
1177 ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) :
1178 PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length);
1179 }
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190 public static int hashCodeAscii(byte[] bytes, int startPos, int length) {
1191 return !hasUnsafe() || !unalignedAccess() || BIG_ENDIAN_NATIVE_ORDER ?
1192 hashCodeAsciiSafe(bytes, startPos, length) :
1193 PlatformDependent0.hashCodeAscii(bytes, startPos, length);
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206 public static int hashCodeAscii(CharSequence bytes) {
1207 final int length = bytes.length();
1208 final int remainingBytes = length & 7;
1209 int hash = HASH_CODE_ASCII_SEED;
1210
1211
1212
1213 if (length >= 32) {
1214 for (int i = length - 8; i >= remainingBytes; i -= 8) {
1215 hash = hashCodeAsciiCompute(bytes, i, hash);
1216 }
1217 } else if (length >= 8) {
1218 hash = hashCodeAsciiCompute(bytes, length - 8, hash);
1219 if (length >= 16) {
1220 hash = hashCodeAsciiCompute(bytes, length - 16, hash);
1221 if (length >= 24) {
1222 hash = hashCodeAsciiCompute(bytes, length - 24, hash);
1223 }
1224 }
1225 }
1226 if (remainingBytes == 0) {
1227 return hash;
1228 }
1229 int offset = 0;
1230 if (remainingBytes != 2 & remainingBytes != 4 & remainingBytes != 6) {
1231 hash = hash * HASH_CODE_C1 + hashCodeAsciiSanitizeByte(bytes.charAt(0));
1232 offset = 1;
1233 }
1234 if (remainingBytes != 1 & remainingBytes != 4 & remainingBytes != 5) {
1235 hash = hash * (offset == 0 ? HASH_CODE_C1 : HASH_CODE_C2)
1236 + hashCodeAsciiSanitize(hashCodeAsciiSanitizeShort(bytes, offset));
1237 offset += 2;
1238 }
1239 if (remainingBytes >= 4) {
1240 return hash * ((offset == 0 | offset == 3) ? HASH_CODE_C1 : HASH_CODE_C2)
1241 + hashCodeAsciiSanitizeInt(bytes, offset);
1242 }
1243 return hash;
1244 }
1245
1246 private static final class Mpsc {
1247 private static final boolean USE_MPSC_CHUNKED_ARRAY_QUEUE;
1248
1249 static {
1250 Object unsafe = null;
1251 if (hasUnsafe()) {
1252
1253
1254
1255 unsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() {
1256 @Override
1257 public Object run() {
1258
1259 return UnsafeAccess.UNSAFE;
1260 }
1261 });
1262 }
1263
1264 if (unsafe == null) {
1265 logger.debug("org.jctools-core.MpscChunkedArrayQueue: unavailable");
1266 USE_MPSC_CHUNKED_ARRAY_QUEUE = false;
1267 } else {
1268 logger.debug("org.jctools-core.MpscChunkedArrayQueue: available");
1269 USE_MPSC_CHUNKED_ARRAY_QUEUE = true;
1270 }
1271 }
1272
1273 static <T> Queue<T> newMpscQueue(final int maxCapacity) {
1274
1275
1276
1277 final int capacity = max(min(maxCapacity, MAX_ALLOWED_MPSC_CAPACITY), MIN_MAX_MPSC_CAPACITY);
1278 return newChunkedMpscQueue(MPSC_CHUNK_SIZE, capacity);
1279 }
1280
1281 static <T> Queue<T> newChunkedMpscQueue(final int chunkSize, final int capacity) {
1282 return USE_MPSC_CHUNKED_ARRAY_QUEUE ? new MpscChunkedArrayQueue<T>(chunkSize, capacity)
1283 : new MpscChunkedAtomicArrayQueue<T>(chunkSize, capacity);
1284 }
1285
1286 static <T> Queue<T> newMpscQueue() {
1287 return USE_MPSC_CHUNKED_ARRAY_QUEUE ? new MpscUnboundedArrayQueue<T>(MPSC_CHUNK_SIZE)
1288 : new MpscUnboundedAtomicArrayQueue<T>(MPSC_CHUNK_SIZE);
1289 }
1290 }
1291
1292
1293
1294
1295
1296
1297 public static <T> Queue<T> newMpscQueue() {
1298 return Mpsc.newMpscQueue();
1299 }
1300
1301
1302
1303
1304
1305 public static <T> Queue<T> newMpscQueue(final int maxCapacity) {
1306 return Mpsc.newMpscQueue(maxCapacity);
1307 }
1308
1309
1310
1311
1312
1313
1314 public static <T> Queue<T> newMpscQueue(final int chunkSize, final int maxCapacity) {
1315 return Mpsc.newChunkedMpscQueue(chunkSize, maxCapacity);
1316 }
1317
1318
1319
1320
1321
1322 public static <T> Queue<T> newSpscQueue() {
1323 return hasUnsafe() ? new SpscLinkedQueue<T>() : new SpscLinkedAtomicQueue<T>();
1324 }
1325
1326
1327
1328
1329
1330 public static <T> Queue<T> newFixedMpscQueue(int capacity) {
1331 return hasUnsafe() ? new MpscArrayQueue<T>(capacity) : new MpscAtomicArrayQueue<T>(capacity);
1332 }
1333
1334
1335
1336
1337
1338
1339 public static <T> Queue<T> newFixedMpscUnpaddedQueue(int capacity) {
1340 return hasUnsafe() ? new MpscUnpaddedArrayQueue<T>(capacity) : new MpscAtomicUnpaddedArrayQueue<T>(capacity);
1341 }
1342
1343
1344
1345
1346
1347 public static <T> Queue<T> newFixedMpmcQueue(int capacity) {
1348 return hasUnsafe() ? new MpmcArrayQueue<T>(capacity) : new MpmcAtomicArrayQueue<T>(capacity);
1349 }
1350
1351
1352
1353
1354 public static ClassLoader getClassLoader(final Class<?> clazz) {
1355 return PlatformDependent0.getClassLoader(clazz);
1356 }
1357
1358
1359
1360
1361 public static ClassLoader getContextClassLoader() {
1362 return PlatformDependent0.getContextClassLoader();
1363 }
1364
1365
1366
1367
1368 public static ClassLoader getSystemClassLoader() {
1369 return PlatformDependent0.getSystemClassLoader();
1370 }
1371
1372
1373
1374
1375 public static <C> Deque<C> newConcurrentDeque() {
1376 return new ConcurrentLinkedDeque<C>();
1377 }
1378
1379
1380
1381
1382
1383 @Deprecated
1384 public static Random threadLocalRandom() {
1385 return ThreadLocalRandom.current();
1386 }
1387
1388 public static void splittableRandomNextBytes(SplittableRandom rng, byte[] data) {
1389 if (javaVersion() >= 10) {
1390 PlatformDependent0.splittableRandomNextBytes(rng, data);
1391 } else {
1392 int i = 0;
1393 int len = data.length;
1394 int longs = len >>> 3;
1395 while (longs-- > 0) {
1396 long val = rng.nextLong();
1397 for (int j = 0; j < Long.BYTES; j++) {
1398 data[i++] = (byte) val;
1399 val = val >>> Byte.SIZE;
1400 }
1401 }
1402 if (i < len) {
1403 long val = rng.nextLong();
1404 for (; i < len; i++) {
1405 data[i++] = (byte) val;
1406 val = val >>> Byte.SIZE;
1407 }
1408 }
1409 }
1410 }
1411
1412 private static boolean isWindows0() {
1413 boolean windows = "windows".equals(NORMALIZED_OS);
1414 if (windows) {
1415 logger.debug("Platform: Windows");
1416 }
1417 return windows;
1418 }
1419
1420 private static boolean isOsx0() {
1421 boolean osx = "osx".equals(NORMALIZED_OS);
1422 if (osx) {
1423 logger.debug("Platform: MacOS");
1424 }
1425 return osx;
1426 }
1427
1428 private static boolean maybeSuperUser0() {
1429 String username = SystemPropertyUtil.get("user.name");
1430 if (isWindows()) {
1431 return "Administrator".equals(username);
1432 }
1433
1434 return "root".equals(username) || "toor".equals(username);
1435 }
1436
1437 private static Throwable unsafeUnavailabilityCause0() {
1438 if (isAndroid()) {
1439 logger.debug("sun.misc.Unsafe: unavailable (Android)");
1440 return new UnsupportedOperationException("sun.misc.Unsafe: unavailable (Android)");
1441 }
1442
1443 if (isIkvmDotNet()) {
1444 logger.debug("sun.misc.Unsafe: unavailable (IKVM.NET)");
1445 return new UnsupportedOperationException("sun.misc.Unsafe: unavailable (IKVM.NET)");
1446 }
1447
1448 Throwable cause = PlatformDependent0.getUnsafeUnavailabilityCause();
1449 if (cause != null) {
1450 return cause;
1451 }
1452
1453 try {
1454 boolean hasUnsafe = PlatformDependent0.hasUnsafe();
1455 logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable");
1456 return null;
1457 } catch (Throwable t) {
1458 logger.trace("Could not determine if Unsafe is available", t);
1459
1460 return new UnsupportedOperationException("Could not determine if Unsafe is available", t);
1461 }
1462 }
1463
1464
1465
1466
1467
1468 public static boolean isJ9Jvm() {
1469 return IS_J9_JVM;
1470 }
1471
1472 private static boolean isJ9Jvm0() {
1473 String vmName = SystemPropertyUtil.get("java.vm.name", "").toLowerCase();
1474 return vmName.startsWith("ibm j9") || vmName.startsWith("eclipse openj9");
1475 }
1476
1477
1478
1479
1480 public static boolean isIkvmDotNet() {
1481 return IS_IVKVM_DOT_NET;
1482 }
1483
1484 private static boolean isIkvmDotNet0() {
1485 String vmName = SystemPropertyUtil.get("java.vm.name", "").toUpperCase(Locale.US);
1486 return vmName.equals("IKVM.NET");
1487 }
1488
1489 private static Pattern getMaxDirectMemorySizeArgPattern() {
1490
1491 Pattern pattern = MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN;
1492 if (pattern == null) {
1493 pattern = Pattern.compile("\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$");
1494 MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = pattern;
1495 }
1496 return pattern;
1497 }
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508 @SuppressWarnings("unchecked")
1509 public static long estimateMaxDirectMemory() {
1510 long maxDirectMemory = PlatformDependent0.bitsMaxDirectMemory();
1511 if (maxDirectMemory > 0) {
1512 return maxDirectMemory;
1513 }
1514
1515 try {
1516
1517
1518 ClassLoader systemClassLoader = getSystemClassLoader();
1519 Class<?> mgmtFactoryClass = Class.forName(
1520 "java.lang.management.ManagementFactory", true, systemClassLoader);
1521 Class<?> runtimeClass = Class.forName(
1522 "java.lang.management.RuntimeMXBean", true, systemClassLoader);
1523
1524 MethodHandles.Lookup lookup = MethodHandles.publicLookup();
1525 MethodHandle getRuntime = lookup.findStatic(
1526 mgmtFactoryClass, "getRuntimeMXBean", methodType(runtimeClass));
1527 MethodHandle getInputArguments = lookup.findVirtual(
1528 runtimeClass, "getInputArguments", methodType(List.class));
1529 List<String> vmArgs = (List<String>) getInputArguments.invoke(getRuntime.invoke());
1530
1531 Pattern maxDirectMemorySizeArgPattern = getMaxDirectMemorySizeArgPattern();
1532
1533 for (int i = vmArgs.size() - 1; i >= 0; i --) {
1534 Matcher m = maxDirectMemorySizeArgPattern.matcher(vmArgs.get(i));
1535 if (!m.matches()) {
1536 continue;
1537 }
1538
1539 maxDirectMemory = Long.parseLong(m.group(1));
1540 switch (m.group(2).charAt(0)) {
1541 case 'k': case 'K':
1542 maxDirectMemory *= 1024;
1543 break;
1544 case 'm': case 'M':
1545 maxDirectMemory *= 1024 * 1024;
1546 break;
1547 case 'g': case 'G':
1548 maxDirectMemory *= 1024 * 1024 * 1024;
1549 break;
1550 default:
1551 break;
1552 }
1553 break;
1554 }
1555 } catch (Throwable ignored) {
1556
1557 }
1558
1559 if (maxDirectMemory <= 0) {
1560 maxDirectMemory = Runtime.getRuntime().maxMemory();
1561 logger.debug("maxDirectMemory: {} bytes (maybe)", maxDirectMemory);
1562 } else {
1563 logger.debug("maxDirectMemory: {} bytes", maxDirectMemory);
1564 }
1565
1566 return maxDirectMemory;
1567 }
1568
1569 private static File tmpdir0() {
1570 File f;
1571 try {
1572 f = toDirectory(SystemPropertyUtil.get("io.netty.tmpdir"));
1573 if (f != null) {
1574 logger.debug("-Dio.netty.tmpdir: {}", f);
1575 return f;
1576 }
1577
1578 f = toDirectory(SystemPropertyUtil.get("java.io.tmpdir"));
1579 if (f != null) {
1580 logger.debug("-Dio.netty.tmpdir: {} (java.io.tmpdir)", f);
1581 return f;
1582 }
1583
1584
1585 if (isWindows()) {
1586 f = toDirectory(System.getenv("TEMP"));
1587 if (f != null) {
1588 logger.debug("-Dio.netty.tmpdir: {} (%TEMP%)", f);
1589 return f;
1590 }
1591
1592 String userprofile = System.getenv("USERPROFILE");
1593 if (userprofile != null) {
1594 f = toDirectory(userprofile + "\\AppData\\Local\\Temp");
1595 if (f != null) {
1596 logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\AppData\\Local\\Temp)", f);
1597 return f;
1598 }
1599
1600 f = toDirectory(userprofile + "\\Local Settings\\Temp");
1601 if (f != null) {
1602 logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\Local Settings\\Temp)", f);
1603 return f;
1604 }
1605 }
1606 } else {
1607 f = toDirectory(System.getenv("TMPDIR"));
1608 if (f != null) {
1609 logger.debug("-Dio.netty.tmpdir: {} ($TMPDIR)", f);
1610 return f;
1611 }
1612 }
1613 } catch (Throwable ignored) {
1614
1615 }
1616
1617
1618 if (isWindows()) {
1619 f = new File("C:\\Windows\\Temp");
1620 } else {
1621 f = new File("/tmp");
1622 }
1623
1624 logger.warn("Failed to get the temporary directory; falling back to: {}", f);
1625 return f;
1626 }
1627
1628 @SuppressWarnings("ResultOfMethodCallIgnored")
1629 private static File toDirectory(String path) {
1630 if (path == null) {
1631 return null;
1632 }
1633
1634 File f = new File(path);
1635 f.mkdirs();
1636
1637 if (!f.isDirectory()) {
1638 return null;
1639 }
1640
1641 try {
1642 return f.getAbsoluteFile();
1643 } catch (Exception ignored) {
1644 return f;
1645 }
1646 }
1647
1648 private static int bitMode0() {
1649
1650 int bitMode = SystemPropertyUtil.getInt("io.netty.bitMode", 0);
1651 if (bitMode > 0) {
1652 logger.debug("-Dio.netty.bitMode: {}", bitMode);
1653 return bitMode;
1654 }
1655
1656
1657 bitMode = SystemPropertyUtil.getInt("sun.arch.data.model", 0);
1658 if (bitMode > 0) {
1659 logger.debug("-Dio.netty.bitMode: {} (sun.arch.data.model)", bitMode);
1660 return bitMode;
1661 }
1662 bitMode = SystemPropertyUtil.getInt("com.ibm.vm.bitmode", 0);
1663 if (bitMode > 0) {
1664 logger.debug("-Dio.netty.bitMode: {} (com.ibm.vm.bitmode)", bitMode);
1665 return bitMode;
1666 }
1667
1668
1669 String arch = SystemPropertyUtil.get("os.arch", "").toLowerCase(Locale.US).trim();
1670 if ("amd64".equals(arch) || "x86_64".equals(arch)) {
1671 bitMode = 64;
1672 } else if ("i386".equals(arch) || "i486".equals(arch) || "i586".equals(arch) || "i686".equals(arch)) {
1673 bitMode = 32;
1674 }
1675
1676 if (bitMode > 0) {
1677 logger.debug("-Dio.netty.bitMode: {} (os.arch: {})", bitMode, arch);
1678 }
1679
1680
1681 String vm = SystemPropertyUtil.get("java.vm.name", "").toLowerCase(Locale.US);
1682 Pattern bitPattern = Pattern.compile("([1-9][0-9]+)-?bit");
1683 Matcher m = bitPattern.matcher(vm);
1684 if (m.find()) {
1685 return Integer.parseInt(m.group(1));
1686 } else {
1687 return 64;
1688 }
1689 }
1690
1691 private static int addressSize0() {
1692 if (!hasUnsafe()) {
1693 return -1;
1694 }
1695 return PlatformDependent0.addressSize();
1696 }
1697
1698 private static long byteArrayBaseOffset0() {
1699 if (!hasUnsafe()) {
1700 return -1;
1701 }
1702 return PlatformDependent0.byteArrayBaseOffset();
1703 }
1704
1705 private static boolean equalsSafe(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
1706 final int end = startPos1 + length;
1707 for (; startPos1 < end; ++startPos1, ++startPos2) {
1708 if (bytes1[startPos1] != bytes2[startPos2]) {
1709 return false;
1710 }
1711 }
1712 return true;
1713 }
1714
1715 private static boolean isZeroSafe(byte[] bytes, int startPos, int length) {
1716 final int end = startPos + length;
1717 for (; startPos < end; ++startPos) {
1718 if (bytes[startPos] != 0) {
1719 return false;
1720 }
1721 }
1722 return true;
1723 }
1724
1725
1726
1727
1728 static int hashCodeAsciiSafe(byte[] bytes, int startPos, int length) {
1729 int hash = HASH_CODE_ASCII_SEED;
1730 final int remainingBytes = length & 7;
1731 final int end = startPos + remainingBytes;
1732 for (int i = startPos - 8 + length; i >= end; i -= 8) {
1733 hash = PlatformDependent0.hashCodeAsciiCompute(getLongSafe(bytes, i), hash);
1734 }
1735 switch(remainingBytes) {
1736 case 7:
1737 return ((hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]))
1738 * HASH_CODE_C2 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos + 1)))
1739 * HASH_CODE_C1 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos + 3));
1740 case 6:
1741 return (hash * HASH_CODE_C1 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos)))
1742 * HASH_CODE_C2 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos + 2));
1743 case 5:
1744 return (hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]))
1745 * HASH_CODE_C2 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos + 1));
1746 case 4:
1747 return hash * HASH_CODE_C1 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos));
1748 case 3:
1749 return (hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]))
1750 * HASH_CODE_C2 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos + 1));
1751 case 2:
1752 return hash * HASH_CODE_C1 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos));
1753 case 1:
1754 return hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]);
1755 default:
1756 return hash;
1757 }
1758 }
1759
1760 public static String normalizedArch() {
1761 return NORMALIZED_ARCH;
1762 }
1763
1764 public static String normalizedOs() {
1765 return NORMALIZED_OS;
1766 }
1767
1768 public static Set<String> normalizedLinuxClassifiers() {
1769 return LINUX_OS_CLASSIFIERS;
1770 }
1771
1772 public static File createTempFile(String prefix, String suffix, File directory) throws IOException {
1773 if (directory == null) {
1774 return Files.createTempFile(prefix, suffix).toFile();
1775 }
1776 return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
1777 }
1778
1779
1780
1781
1782
1783
1784
1785 private static void addClassifier(Set<String> dest, String... maybeClassifiers) {
1786 for (String id : maybeClassifiers) {
1787 if (isAllowedClassifier(id)) {
1788 dest.add(id);
1789 }
1790 }
1791 }
1792
1793 private static boolean isAllowedClassifier(String classifier) {
1794 switch (classifier) {
1795 case "fedora":
1796 case "suse":
1797 case "arch":
1798 return true;
1799 default:
1800 return false;
1801 }
1802 }
1803
1804
1805 private static String normalizeOsReleaseVariableValue(String value) {
1806 String trimmed = value.trim();
1807 StringBuilder sb = new StringBuilder(trimmed.length());
1808 for (int i = 0; i < trimmed.length(); i++) {
1809 char c = trimmed.charAt(i);
1810 if (c != '"' && c != '\'') {
1811 sb.append(c);
1812 }
1813 }
1814 return sb.toString();
1815 }
1816
1817
1818 private static String normalize(String value) {
1819 StringBuilder sb = new StringBuilder(value.length());
1820 for (int i = 0; i < value.length(); i++) {
1821 char c = Character.toLowerCase(value.charAt(i));
1822 if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) {
1823 sb.append(c);
1824 }
1825 }
1826 return sb.toString();
1827 }
1828
1829 private static String normalizeArch(String value) {
1830 value = normalize(value);
1831 switch (value) {
1832 case "x8664":
1833 case "amd64":
1834 case "ia32e":
1835 case "em64t":
1836 case "x64":
1837 return "x86_64";
1838
1839 case "x8632":
1840 case "x86":
1841 case "i386":
1842 case "i486":
1843 case "i586":
1844 case "i686":
1845 case "ia32":
1846 case "x32":
1847 return "x86_32";
1848
1849 case "ia64":
1850 case "itanium64":
1851 return "itanium_64";
1852
1853 case "sparc":
1854 case "sparc32":
1855 return "sparc_32";
1856
1857 case "sparcv9":
1858 case "sparc64":
1859 return "sparc_64";
1860
1861 case "arm":
1862 case "arm32":
1863 return "arm_32";
1864
1865 case "aarch64":
1866 return "aarch_64";
1867
1868 case "riscv64":
1869 return "riscv64";
1870
1871 case "ppc":
1872 case "ppc32":
1873 return "ppc_32";
1874
1875 case "ppc64":
1876 return "ppc_64";
1877
1878 case "ppc64le":
1879 return "ppcle_64";
1880
1881 case "s390":
1882 return "s390_32";
1883
1884 case "s390x":
1885 return "s390_64";
1886
1887 case "loongarch64":
1888 return "loongarch_64";
1889
1890 default:
1891 return "unknown";
1892 }
1893 }
1894
1895 private static String normalizeOs(String value) {
1896 value = normalize(value);
1897 if (value.startsWith("aix")) {
1898 return "aix";
1899 }
1900 if (value.startsWith("hpux")) {
1901 return "hpux";
1902 }
1903 if (value.startsWith("os400")) {
1904
1905 if (value.length() <= 5 || !Character.isDigit(value.charAt(5))) {
1906 return "os400";
1907 }
1908 }
1909 if (value.startsWith("linux")) {
1910 return "linux";
1911 }
1912 if (value.startsWith("macosx") || value.startsWith("osx") || value.startsWith("darwin")) {
1913 return "osx";
1914 }
1915 if (value.startsWith("freebsd")) {
1916 return "freebsd";
1917 }
1918 if (value.startsWith("openbsd")) {
1919 return "openbsd";
1920 }
1921 if (value.startsWith("netbsd")) {
1922 return "netbsd";
1923 }
1924 if (value.startsWith("solaris") || value.startsWith("sunos")) {
1925 return "sunos";
1926 }
1927 if (value.startsWith("windows")) {
1928 return "windows";
1929 }
1930
1931 return "unknown";
1932 }
1933
1934
1935
1936
1937 public static boolean isJfrEnabled() {
1938 return JFR;
1939 }
1940
1941 private PlatformDependent() {
1942
1943 }
1944 }