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