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