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