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