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