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 private static void incrementMemoryCounter(int capacity) {
1060 if (DIRECT_MEMORY_COUNTER != null) {
1061 long newUsedMemory = DIRECT_MEMORY_COUNTER.addAndGet(capacity);
1062 if (newUsedMemory > DIRECT_MEMORY_LIMIT) {
1063 DIRECT_MEMORY_COUNTER.addAndGet(-capacity);
1064 throw new OutOfDirectMemoryError("failed to allocate " + capacity
1065 + " byte(s) of direct memory (used: " + (newUsedMemory - capacity)
1066 + ", max: " + DIRECT_MEMORY_LIMIT + ')');
1067 }
1068 }
1069 }
1070
1071 private static void decrementMemoryCounter(int capacity) {
1072 if (DIRECT_MEMORY_COUNTER != null) {
1073 long usedMemory = DIRECT_MEMORY_COUNTER.addAndGet(-capacity);
1074 assert usedMemory >= 0;
1075 }
1076 }
1077
1078 public static boolean useDirectBufferNoCleaner() {
1079 return USE_DIRECT_BUFFER_NO_CLEANER;
1080 }
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093 public static boolean equals(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
1094 if (javaVersion() > 8 && (startPos2 | startPos1 | (bytes1.length - length) | bytes2.length - length) == 0) {
1095 return Arrays.equals(bytes1, bytes2);
1096 }
1097 return !hasUnsafe() || !unalignedAccess() ?
1098 equalsSafe(bytes1, startPos1, bytes2, startPos2, length) :
1099 PlatformDependent0.equals(bytes1, startPos1, bytes2, startPos2, length);
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109 public static boolean isZero(byte[] bytes, int startPos, int length) {
1110 return !hasUnsafe() || !unalignedAccess() ?
1111 isZeroSafe(bytes, startPos, length) :
1112 PlatformDependent0.isZero(bytes, startPos, length);
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136 public static int equalsConstantTime(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
1137 return !hasUnsafe() || !unalignedAccess() ?
1138 ConstantTimeUtils.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length) :
1139 PlatformDependent0.equalsConstantTime(bytes1, startPos1, bytes2, startPos2, length);
1140 }
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151 public static int hashCodeAscii(byte[] bytes, int startPos, int length) {
1152 return !hasUnsafe() || !unalignedAccess() ?
1153 hashCodeAsciiSafe(bytes, startPos, length) :
1154 PlatformDependent0.hashCodeAscii(bytes, startPos, length);
1155 }
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167 public static int hashCodeAscii(CharSequence bytes) {
1168 final int length = bytes.length();
1169 final int remainingBytes = length & 7;
1170 int hash = HASH_CODE_ASCII_SEED;
1171
1172
1173
1174 if (length >= 32) {
1175 for (int i = length - 8; i >= remainingBytes; i -= 8) {
1176 hash = hashCodeAsciiCompute(bytes, i, hash);
1177 }
1178 } else if (length >= 8) {
1179 hash = hashCodeAsciiCompute(bytes, length - 8, hash);
1180 if (length >= 16) {
1181 hash = hashCodeAsciiCompute(bytes, length - 16, hash);
1182 if (length >= 24) {
1183 hash = hashCodeAsciiCompute(bytes, length - 24, hash);
1184 }
1185 }
1186 }
1187 if (remainingBytes == 0) {
1188 return hash;
1189 }
1190 int offset = 0;
1191 if (remainingBytes != 2 & remainingBytes != 4 & remainingBytes != 6) {
1192 hash = hash * HASH_CODE_C1 + hashCodeAsciiSanitizeByte(bytes.charAt(0));
1193 offset = 1;
1194 }
1195 if (remainingBytes != 1 & remainingBytes != 4 & remainingBytes != 5) {
1196 hash = hash * (offset == 0 ? HASH_CODE_C1 : HASH_CODE_C2)
1197 + hashCodeAsciiSanitize(hashCodeAsciiSanitizeShort(bytes, offset));
1198 offset += 2;
1199 }
1200 if (remainingBytes >= 4) {
1201 return hash * ((offset == 0 | offset == 3) ? HASH_CODE_C1 : HASH_CODE_C2)
1202 + hashCodeAsciiSanitizeInt(bytes, offset);
1203 }
1204 return hash;
1205 }
1206
1207 private static final class Mpsc {
1208 private static final boolean USE_MPSC_CHUNKED_ARRAY_QUEUE;
1209
1210 static {
1211 Object unsafe = null;
1212 if (hasUnsafe()) {
1213
1214
1215
1216 unsafe = AccessController.doPrivileged(new PrivilegedAction<Object>() {
1217 @Override
1218 public Object run() {
1219
1220 return UnsafeAccess.UNSAFE;
1221 }
1222 });
1223 }
1224
1225 if (unsafe == null) {
1226 logger.debug("org.jctools-core.MpscChunkedArrayQueue: unavailable");
1227 USE_MPSC_CHUNKED_ARRAY_QUEUE = false;
1228 } else {
1229 logger.debug("org.jctools-core.MpscChunkedArrayQueue: available");
1230 USE_MPSC_CHUNKED_ARRAY_QUEUE = true;
1231 }
1232 }
1233
1234 static <T> Queue<T> newMpscQueue(final int maxCapacity) {
1235
1236
1237
1238 final int capacity = max(min(maxCapacity, MAX_ALLOWED_MPSC_CAPACITY), MIN_MAX_MPSC_CAPACITY);
1239 return newChunkedMpscQueue(MPSC_CHUNK_SIZE, capacity);
1240 }
1241
1242 static <T> Queue<T> newChunkedMpscQueue(final int chunkSize, final int capacity) {
1243 return USE_MPSC_CHUNKED_ARRAY_QUEUE ? new MpscChunkedArrayQueue<T>(chunkSize, capacity)
1244 : new MpscChunkedAtomicArrayQueue<T>(chunkSize, capacity);
1245 }
1246
1247 static <T> Queue<T> newMpscQueue() {
1248 return USE_MPSC_CHUNKED_ARRAY_QUEUE ? new MpscUnboundedArrayQueue<T>(MPSC_CHUNK_SIZE)
1249 : new MpscUnboundedAtomicArrayQueue<T>(MPSC_CHUNK_SIZE);
1250 }
1251 }
1252
1253
1254
1255
1256
1257
1258 public static <T> Queue<T> newMpscQueue() {
1259 return Mpsc.newMpscQueue();
1260 }
1261
1262
1263
1264
1265
1266 public static <T> Queue<T> newMpscQueue(final int maxCapacity) {
1267 return Mpsc.newMpscQueue(maxCapacity);
1268 }
1269
1270
1271
1272
1273
1274
1275 public static <T> Queue<T> newMpscQueue(final int chunkSize, final int maxCapacity) {
1276 return Mpsc.newChunkedMpscQueue(chunkSize, maxCapacity);
1277 }
1278
1279
1280
1281
1282
1283 public static <T> Queue<T> newSpscQueue() {
1284 return hasUnsafe() ? new SpscLinkedQueue<T>() : new SpscLinkedAtomicQueue<T>();
1285 }
1286
1287
1288
1289
1290
1291 public static <T> Queue<T> newFixedMpscQueue(int capacity) {
1292 return hasUnsafe() ? new MpscArrayQueue<T>(capacity) : new MpscAtomicArrayQueue<T>(capacity);
1293 }
1294
1295
1296
1297
1298
1299
1300 public static <T> Queue<T> newFixedMpscUnpaddedQueue(int capacity) {
1301 return hasUnsafe() ? new MpscUnpaddedArrayQueue<T>(capacity) : new MpscAtomicUnpaddedArrayQueue<T>(capacity);
1302 }
1303
1304
1305
1306
1307
1308 public static <T> Queue<T> newFixedMpmcQueue(int capacity) {
1309 return hasUnsafe() ? new MpmcArrayQueue<T>(capacity) : new MpmcAtomicArrayQueue<T>(capacity);
1310 }
1311
1312
1313
1314
1315 public static ClassLoader getClassLoader(final Class<?> clazz) {
1316 return PlatformDependent0.getClassLoader(clazz);
1317 }
1318
1319
1320
1321
1322 public static ClassLoader getContextClassLoader() {
1323 return PlatformDependent0.getContextClassLoader();
1324 }
1325
1326
1327
1328
1329 public static ClassLoader getSystemClassLoader() {
1330 return PlatformDependent0.getSystemClassLoader();
1331 }
1332
1333
1334
1335
1336 public static <C> Deque<C> newConcurrentDeque() {
1337 return new ConcurrentLinkedDeque<C>();
1338 }
1339
1340
1341
1342
1343
1344 @Deprecated
1345 public static Random threadLocalRandom() {
1346 return ThreadLocalRandom.current();
1347 }
1348
1349 private static boolean isWindows0() {
1350 boolean windows = "windows".equals(NORMALIZED_OS);
1351 if (windows) {
1352 logger.debug("Platform: Windows");
1353 }
1354 return windows;
1355 }
1356
1357 private static boolean isOsx0() {
1358 boolean osx = "osx".equals(NORMALIZED_OS);
1359 if (osx) {
1360 logger.debug("Platform: MacOS");
1361 }
1362 return osx;
1363 }
1364
1365 private static boolean maybeSuperUser0() {
1366 String username = SystemPropertyUtil.get("user.name");
1367 if (isWindows()) {
1368 return "Administrator".equals(username);
1369 }
1370
1371 return "root".equals(username) || "toor".equals(username);
1372 }
1373
1374 private static Throwable unsafeUnavailabilityCause0() {
1375 if (isAndroid()) {
1376 logger.debug("sun.misc.Unsafe: unavailable (Android)");
1377 return new UnsupportedOperationException("sun.misc.Unsafe: unavailable (Android)");
1378 }
1379
1380 if (isIkvmDotNet()) {
1381 logger.debug("sun.misc.Unsafe: unavailable (IKVM.NET)");
1382 return new UnsupportedOperationException("sun.misc.Unsafe: unavailable (IKVM.NET)");
1383 }
1384
1385 Throwable cause = PlatformDependent0.getUnsafeUnavailabilityCause();
1386 if (cause != null) {
1387 return cause;
1388 }
1389
1390 try {
1391 boolean hasUnsafe = PlatformDependent0.hasUnsafe();
1392 logger.debug("sun.misc.Unsafe: {}", hasUnsafe ? "available" : "unavailable");
1393 return null;
1394 } catch (Throwable t) {
1395 logger.trace("Could not determine if Unsafe is available", t);
1396
1397 return new UnsupportedOperationException("Could not determine if Unsafe is available", t);
1398 }
1399 }
1400
1401
1402
1403
1404
1405 public static boolean isJ9Jvm() {
1406 return IS_J9_JVM;
1407 }
1408
1409 private static boolean isJ9Jvm0() {
1410 String vmName = SystemPropertyUtil.get("java.vm.name", "").toLowerCase();
1411 return vmName.startsWith("ibm j9") || vmName.startsWith("eclipse openj9");
1412 }
1413
1414
1415
1416
1417 public static boolean isIkvmDotNet() {
1418 return IS_IVKVM_DOT_NET;
1419 }
1420
1421 private static boolean isIkvmDotNet0() {
1422 String vmName = SystemPropertyUtil.get("java.vm.name", "").toUpperCase(Locale.US);
1423 return vmName.equals("IKVM.NET");
1424 }
1425
1426 private static Pattern getMaxDirectMemorySizeArgPattern() {
1427
1428 Pattern pattern = MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN;
1429 if (pattern == null) {
1430 pattern = Pattern.compile("\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$");
1431 MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = pattern;
1432 }
1433 return pattern;
1434 }
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445 @SuppressWarnings("unchecked")
1446 public static long estimateMaxDirectMemory() {
1447 long maxDirectMemory = PlatformDependent0.bitsMaxDirectMemory();
1448 if (maxDirectMemory > 0) {
1449 return maxDirectMemory;
1450 }
1451
1452 try {
1453
1454
1455 ClassLoader systemClassLoader = getSystemClassLoader();
1456 Class<?> mgmtFactoryClass = Class.forName(
1457 "java.lang.management.ManagementFactory", true, systemClassLoader);
1458 Class<?> runtimeClass = Class.forName(
1459 "java.lang.management.RuntimeMXBean", true, systemClassLoader);
1460
1461 MethodHandles.Lookup lookup = MethodHandles.publicLookup();
1462 MethodHandle getRuntime = lookup.findStatic(
1463 mgmtFactoryClass, "getRuntimeMXBean", methodType(runtimeClass));
1464 MethodHandle getInputArguments = lookup.findVirtual(
1465 runtimeClass, "getInputArguments", methodType(List.class));
1466 List<String> vmArgs = (List<String>) getInputArguments.invoke(getRuntime.invoke());
1467
1468 Pattern maxDirectMemorySizeArgPattern = getMaxDirectMemorySizeArgPattern();
1469
1470 for (int i = vmArgs.size() - 1; i >= 0; i --) {
1471 Matcher m = maxDirectMemorySizeArgPattern.matcher(vmArgs.get(i));
1472 if (!m.matches()) {
1473 continue;
1474 }
1475
1476 maxDirectMemory = Long.parseLong(m.group(1));
1477 switch (m.group(2).charAt(0)) {
1478 case 'k': case 'K':
1479 maxDirectMemory *= 1024;
1480 break;
1481 case 'm': case 'M':
1482 maxDirectMemory *= 1024 * 1024;
1483 break;
1484 case 'g': case 'G':
1485 maxDirectMemory *= 1024 * 1024 * 1024;
1486 break;
1487 default:
1488 break;
1489 }
1490 break;
1491 }
1492 } catch (Throwable ignored) {
1493
1494 }
1495
1496 if (maxDirectMemory <= 0) {
1497 maxDirectMemory = Runtime.getRuntime().maxMemory();
1498 logger.debug("maxDirectMemory: {} bytes (maybe)", maxDirectMemory);
1499 } else {
1500 logger.debug("maxDirectMemory: {} bytes", maxDirectMemory);
1501 }
1502
1503 return maxDirectMemory;
1504 }
1505
1506 private static File tmpdir0() {
1507 File f;
1508 try {
1509 f = toDirectory(SystemPropertyUtil.get("io.netty.tmpdir"));
1510 if (f != null) {
1511 logger.debug("-Dio.netty.tmpdir: {}", f);
1512 return f;
1513 }
1514
1515 f = toDirectory(SystemPropertyUtil.get("java.io.tmpdir"));
1516 if (f != null) {
1517 logger.debug("-Dio.netty.tmpdir: {} (java.io.tmpdir)", f);
1518 return f;
1519 }
1520
1521
1522 if (isWindows()) {
1523 f = toDirectory(System.getenv("TEMP"));
1524 if (f != null) {
1525 logger.debug("-Dio.netty.tmpdir: {} (%TEMP%)", f);
1526 return f;
1527 }
1528
1529 String userprofile = System.getenv("USERPROFILE");
1530 if (userprofile != null) {
1531 f = toDirectory(userprofile + "\\AppData\\Local\\Temp");
1532 if (f != null) {
1533 logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\AppData\\Local\\Temp)", f);
1534 return f;
1535 }
1536
1537 f = toDirectory(userprofile + "\\Local Settings\\Temp");
1538 if (f != null) {
1539 logger.debug("-Dio.netty.tmpdir: {} (%USERPROFILE%\\Local Settings\\Temp)", f);
1540 return f;
1541 }
1542 }
1543 } else {
1544 f = toDirectory(System.getenv("TMPDIR"));
1545 if (f != null) {
1546 logger.debug("-Dio.netty.tmpdir: {} ($TMPDIR)", f);
1547 return f;
1548 }
1549 }
1550 } catch (Throwable ignored) {
1551
1552 }
1553
1554
1555 if (isWindows()) {
1556 f = new File("C:\\Windows\\Temp");
1557 } else {
1558 f = new File("/tmp");
1559 }
1560
1561 logger.warn("Failed to get the temporary directory; falling back to: {}", f);
1562 return f;
1563 }
1564
1565 @SuppressWarnings("ResultOfMethodCallIgnored")
1566 private static File toDirectory(String path) {
1567 if (path == null) {
1568 return null;
1569 }
1570
1571 File f = new File(path);
1572 f.mkdirs();
1573
1574 if (!f.isDirectory()) {
1575 return null;
1576 }
1577
1578 try {
1579 return f.getAbsoluteFile();
1580 } catch (Exception ignored) {
1581 return f;
1582 }
1583 }
1584
1585 private static int bitMode0() {
1586
1587 int bitMode = SystemPropertyUtil.getInt("io.netty.bitMode", 0);
1588 if (bitMode > 0) {
1589 logger.debug("-Dio.netty.bitMode: {}", bitMode);
1590 return bitMode;
1591 }
1592
1593
1594 bitMode = SystemPropertyUtil.getInt("sun.arch.data.model", 0);
1595 if (bitMode > 0) {
1596 logger.debug("-Dio.netty.bitMode: {} (sun.arch.data.model)", bitMode);
1597 return bitMode;
1598 }
1599 bitMode = SystemPropertyUtil.getInt("com.ibm.vm.bitmode", 0);
1600 if (bitMode > 0) {
1601 logger.debug("-Dio.netty.bitMode: {} (com.ibm.vm.bitmode)", bitMode);
1602 return bitMode;
1603 }
1604
1605
1606 String arch = SystemPropertyUtil.get("os.arch", "").toLowerCase(Locale.US).trim();
1607 if ("amd64".equals(arch) || "x86_64".equals(arch)) {
1608 bitMode = 64;
1609 } else if ("i386".equals(arch) || "i486".equals(arch) || "i586".equals(arch) || "i686".equals(arch)) {
1610 bitMode = 32;
1611 }
1612
1613 if (bitMode > 0) {
1614 logger.debug("-Dio.netty.bitMode: {} (os.arch: {})", bitMode, arch);
1615 }
1616
1617
1618 String vm = SystemPropertyUtil.get("java.vm.name", "").toLowerCase(Locale.US);
1619 Pattern bitPattern = Pattern.compile("([1-9][0-9]+)-?bit");
1620 Matcher m = bitPattern.matcher(vm);
1621 if (m.find()) {
1622 return Integer.parseInt(m.group(1));
1623 } else {
1624 return 64;
1625 }
1626 }
1627
1628 private static int addressSize0() {
1629 if (!hasUnsafe()) {
1630 return -1;
1631 }
1632 return PlatformDependent0.addressSize();
1633 }
1634
1635 private static long byteArrayBaseOffset0() {
1636 if (!hasUnsafe()) {
1637 return -1;
1638 }
1639 return PlatformDependent0.byteArrayBaseOffset();
1640 }
1641
1642 private static boolean equalsSafe(byte[] bytes1, int startPos1, byte[] bytes2, int startPos2, int length) {
1643 final int end = startPos1 + length;
1644 for (; startPos1 < end; ++startPos1, ++startPos2) {
1645 if (bytes1[startPos1] != bytes2[startPos2]) {
1646 return false;
1647 }
1648 }
1649 return true;
1650 }
1651
1652 private static boolean isZeroSafe(byte[] bytes, int startPos, int length) {
1653 final int end = startPos + length;
1654 for (; startPos < end; ++startPos) {
1655 if (bytes[startPos] != 0) {
1656 return false;
1657 }
1658 }
1659 return true;
1660 }
1661
1662
1663
1664
1665 static int hashCodeAsciiSafe(byte[] bytes, int startPos, int length) {
1666 int hash = HASH_CODE_ASCII_SEED;
1667 final int remainingBytes = length & 7;
1668 final int end = startPos + remainingBytes;
1669 for (int i = startPos - 8 + length; i >= end; i -= 8) {
1670 hash = PlatformDependent0.hashCodeAsciiCompute(getLongSafe(bytes, i), hash);
1671 }
1672 switch(remainingBytes) {
1673 case 7:
1674 return ((hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]))
1675 * HASH_CODE_C2 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos + 1)))
1676 * HASH_CODE_C1 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos + 3));
1677 case 6:
1678 return (hash * HASH_CODE_C1 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos)))
1679 * HASH_CODE_C2 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos + 2));
1680 case 5:
1681 return (hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]))
1682 * HASH_CODE_C2 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos + 1));
1683 case 4:
1684 return hash * HASH_CODE_C1 + hashCodeAsciiSanitize(getIntSafe(bytes, startPos));
1685 case 3:
1686 return (hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]))
1687 * HASH_CODE_C2 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos + 1));
1688 case 2:
1689 return hash * HASH_CODE_C1 + hashCodeAsciiSanitize(getShortSafe(bytes, startPos));
1690 case 1:
1691 return hash * HASH_CODE_C1 + hashCodeAsciiSanitize(bytes[startPos]);
1692 default:
1693 return hash;
1694 }
1695 }
1696
1697 public static String normalizedArch() {
1698 return NORMALIZED_ARCH;
1699 }
1700
1701 public static String normalizedOs() {
1702 return NORMALIZED_OS;
1703 }
1704
1705 public static Set<String> normalizedLinuxClassifiers() {
1706 return LINUX_OS_CLASSIFIERS;
1707 }
1708
1709 public static File createTempFile(String prefix, String suffix, File directory) throws IOException {
1710 if (directory == null) {
1711 return Files.createTempFile(prefix, suffix).toFile();
1712 }
1713 return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
1714 }
1715
1716
1717
1718
1719
1720
1721
1722 private static void addClassifier(Set<String> dest, String... maybeClassifiers) {
1723 for (String id : maybeClassifiers) {
1724 if (isAllowedClassifier(id)) {
1725 dest.add(id);
1726 }
1727 }
1728 }
1729
1730 private static boolean isAllowedClassifier(String classifier) {
1731 switch (classifier) {
1732 case "fedora":
1733 case "suse":
1734 case "arch":
1735 return true;
1736 default:
1737 return false;
1738 }
1739 }
1740
1741
1742 private static String normalizeOsReleaseVariableValue(String value) {
1743 String trimmed = value.trim();
1744 StringBuilder sb = new StringBuilder(trimmed.length());
1745 for (int i = 0; i < trimmed.length(); i++) {
1746 char c = trimmed.charAt(i);
1747 if (c != '"' && c != '\'') {
1748 sb.append(c);
1749 }
1750 }
1751 return sb.toString();
1752 }
1753
1754
1755 private static String normalize(String value) {
1756 StringBuilder sb = new StringBuilder(value.length());
1757 for (int i = 0; i < value.length(); i++) {
1758 char c = Character.toLowerCase(value.charAt(i));
1759 if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) {
1760 sb.append(c);
1761 }
1762 }
1763 return sb.toString();
1764 }
1765
1766 private static String normalizeArch(String value) {
1767 value = normalize(value);
1768 switch (value) {
1769 case "x8664":
1770 case "amd64":
1771 case "ia32e":
1772 case "em64t":
1773 case "x64":
1774 return "x86_64";
1775
1776 case "x8632":
1777 case "x86":
1778 case "i386":
1779 case "i486":
1780 case "i586":
1781 case "i686":
1782 case "ia32":
1783 case "x32":
1784 return "x86_32";
1785
1786 case "ia64":
1787 case "itanium64":
1788 return "itanium_64";
1789
1790 case "sparc":
1791 case "sparc32":
1792 return "sparc_32";
1793
1794 case "sparcv9":
1795 case "sparc64":
1796 return "sparc_64";
1797
1798 case "arm":
1799 case "arm32":
1800 return "arm_32";
1801
1802 case "aarch64":
1803 return "aarch_64";
1804
1805 case "riscv64":
1806 return "riscv64";
1807
1808 case "ppc":
1809 case "ppc32":
1810 return "ppc_32";
1811
1812 case "ppc64":
1813 return "ppc_64";
1814
1815 case "ppc64le":
1816 return "ppcle_64";
1817
1818 case "s390":
1819 return "s390_32";
1820
1821 case "s390x":
1822 return "s390_64";
1823
1824 case "loongarch64":
1825 return "loongarch_64";
1826
1827 default:
1828 return "unknown";
1829 }
1830 }
1831
1832 private static String normalizeOs(String value) {
1833 value = normalize(value);
1834 if (value.startsWith("aix")) {
1835 return "aix";
1836 }
1837 if (value.startsWith("hpux")) {
1838 return "hpux";
1839 }
1840 if (value.startsWith("os400")) {
1841
1842 if (value.length() <= 5 || !Character.isDigit(value.charAt(5))) {
1843 return "os400";
1844 }
1845 }
1846 if (value.startsWith("linux")) {
1847 return "linux";
1848 }
1849 if (value.startsWith("macosx") || value.startsWith("osx") || value.startsWith("darwin")) {
1850 return "osx";
1851 }
1852 if (value.startsWith("freebsd")) {
1853 return "freebsd";
1854 }
1855 if (value.startsWith("openbsd")) {
1856 return "openbsd";
1857 }
1858 if (value.startsWith("netbsd")) {
1859 return "netbsd";
1860 }
1861 if (value.startsWith("solaris") || value.startsWith("sunos")) {
1862 return "sunos";
1863 }
1864 if (value.startsWith("windows")) {
1865 return "windows";
1866 }
1867
1868 return "unknown";
1869 }
1870
1871
1872
1873
1874 public static boolean isJfrEnabled() {
1875 return JFR;
1876 }
1877
1878 private PlatformDependent() {
1879
1880 }
1881 }