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