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