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