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