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