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