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