From 2a3fa76271b0f30c46368530aafd869ebac364b8 Mon Sep 17 00:00:00 2001 From: yanyir Date: Mon, 25 Sep 2023 01:19:08 +0800 Subject: [PATCH 1/3] Remove ThreadLocalRandom.java --- .../taobao/arthas/core/util/StringUtils.java | 1 + .../arthas/core/util/ThreadLocalRandom.java | 271 ------------------ .../arthas/core/util/metrics/RateCounter.java | 3 +- 3 files changed, 2 insertions(+), 273 deletions(-) delete mode 100644 core/src/main/java/com/taobao/arthas/core/util/ThreadLocalRandom.java diff --git a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java index d243687b3b..58993479b5 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java +++ b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java @@ -30,6 +30,7 @@ import java.util.Set; import java.util.StringTokenizer; import java.util.TreeSet; +import java.util.concurrent.ThreadLocalRandom; import com.alibaba.arthas.deps.org.slf4j.Logger; import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; diff --git a/core/src/main/java/com/taobao/arthas/core/util/ThreadLocalRandom.java b/core/src/main/java/com/taobao/arthas/core/util/ThreadLocalRandom.java deleted file mode 100644 index 3d2a7c4df5..0000000000 --- a/core/src/main/java/com/taobao/arthas/core/util/ThreadLocalRandom.java +++ /dev/null @@ -1,271 +0,0 @@ -package com.taobao.arthas.core.util; -import java.security.SecureRandom; -import java.util.Random; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -/** - * A random number generator isolated to the current thread. Like the global {@link java.util.Random} generator used by - * the {@link java.lang.Math} class, a {@code ThreadLocalRandom} is initialized with an internally generated seed that - * may not otherwise be modified. When applicable, use of {@code ThreadLocalRandom} rather than shared {@code Random} - * objects in concurrent programs will typically encounter much less overhead and contention. Use of - * {@code ThreadLocalRandom} is particularly appropriate when multiple tasks (for example, each a - * {@link io.netty.util.internal.chmv8.ForkJoinTask}) use random numbers in parallel in thread pools. - * - *

- * Usages of this class should typically be of the form: {@code ThreadLocalRandom.current().nextX(...)} (where {@code X} - * is {@code Int}, {@code Long}, etc). When all usages are of this form, it is never possible to accidently share a - * {@code ThreadLocalRandom} across multiple threads. - * - *

- * This class also provides additional commonly used bounded random generation methods. - * - * //since 1.7 //author Doug Lea - */ -@SuppressWarnings("all") -public class ThreadLocalRandom extends Random { - private static final AtomicLong seedUniquifier = new AtomicLong(); - - private static volatile long initialSeedUniquifier; - - public static void setInitialSeedUniquifier(long initialSeedUniquifier) { - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier; - } - - public static synchronized long getInitialSeedUniquifier() { - // Use the value set via the setter. - long initialSeedUniquifier = ThreadLocalRandom.initialSeedUniquifier; - // Otherwise, generate one. - if (initialSeedUniquifier == 0) { - // Try to generate a real random number from /dev/random. - // Get from a different thread to avoid blocking indefinitely on a machine without much entrophy. - final BlockingQueue queue = new LinkedBlockingQueue(); - Thread generatorThread = new Thread("initialSeedUniquifierGenerator") { - @Override - public void run() { - SecureRandom random = new SecureRandom(); // Get the real random seed from /dev/random - queue.add(random.nextLong()); - } - }; - generatorThread.start(); - - // Get the random seed from the thread with timeout. - final long timeoutSeconds = 3; - final long deadLine = System.nanoTime() + TimeUnit.SECONDS.toNanos(timeoutSeconds); - for (;;) { - long waitTime = deadLine - System.nanoTime(); - if (waitTime <= 0) { - break; - } - - try { - Long result = queue.poll(waitTime, TimeUnit.NANOSECONDS); - if (result != null) { - initialSeedUniquifier = result; - break; - } - } catch (InterruptedException ignore) { - // Ignore - } - } - - // Just in case the initialSeedUniquifier is zero or some other constant - initialSeedUniquifier ^= 0x3255ecdc33bae119L; // just a meaningless random number - initialSeedUniquifier ^= Long.reverse(System.nanoTime()); - - ThreadLocalRandom.initialSeedUniquifier = initialSeedUniquifier; - } - - return initialSeedUniquifier; - } - - private static long newSeed() { - for (;;) { - final long current = seedUniquifier.get(); - final long actualCurrent = current != 0 ? current : getInitialSeedUniquifier(); - - // L'Ecuyer, "Tables of Linear Congruential Generators of Different Sizes and Good Lattice Structure", 1999 - final long next = actualCurrent * 181783497276652981L; - - if (seedUniquifier.compareAndSet(current, next)) { - return next ^ System.nanoTime(); - } - } - } - - // same constants as Random, but must be redeclared because private - private static final long multiplier = 0x5DEECE66DL; - private static final long addend = 0xBL; - private static final long mask = (1L << 48) - 1; - - /** - * The random seed. We can't use super.seed. - */ - private long rnd; - - /** - * Initialization flag to permit calls to setSeed to succeed only while executing the Random constructor. We can't - * allow others since it would cause setting seed in one part of a program to unintentionally impact other usages by - * the thread. - */ - boolean initialized; - - // Padding to help avoid memory contention among seed updates in - // different TLRs in the common case that they are located near - // each other. - private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7; - - /** - * Constructor called only by localRandom.initialValue. - */ - ThreadLocalRandom() { - super(newSeed()); - initialized = true; - } - - /** - * The actual ThreadLocal - */ - private static final ThreadLocal localRandom = new ThreadLocal() { - protected ThreadLocalRandom initialValue() { - return new ThreadLocalRandom(); - } - }; - - /** - * Returns the current thread's {@code ThreadLocalRandom}. - * - * @return the current thread's {@code ThreadLocalRandom} - */ - public static ThreadLocalRandom current() { - return localRandom.get(); - } - - /** - * Throws {@code UnsupportedOperationException}. Setting seeds in this generator is not supported. - * - * @throws UnsupportedOperationException - * always - */ - public void setSeed(long seed) { - if (initialized) { - throw new UnsupportedOperationException(); - } - rnd = (seed ^ multiplier) & mask; - } - - protected int next(int bits) { - rnd = (rnd * multiplier + addend) & mask; - return (int) (rnd >>> (48 - bits)); - } - - /** - * Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound - * (exclusive). - * - * @param least - * the least value returned - * @param bound - * the upper bound (exclusive) - * @throws IllegalArgumentException - * if least greater than or equal to bound - * @return the next value - */ - public int nextInt(int least, int bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextInt(bound - least) + least; - } - - /** - * Returns a pseudorandom, uniformly distributed value between 0 (inclusive) and the specified value (exclusive). - * - * @param n - * the bound on the random number to be returned. Must be positive. - * @return the next value - * @throws IllegalArgumentException - * if n is not positive - */ - public long nextLong(long n) { - if (n <= 0) { - throw new IllegalArgumentException("n must be positive"); - } - - // Divide n by two until small enough for nextInt. On each - // iteration (at most 31 of them but usually much less), - // randomly choose both whether to include high bit in result - // (offset) and whether to continue with the lower vs upper - // half (which makes a difference only if odd). - long offset = 0; - while (n >= Integer.MAX_VALUE) { - int bits = next(2); - long half = n >>> 1; - long nextn = ((bits & 2) == 0) ? half : n - half; - if ((bits & 1) == 0) { - offset += n - nextn; - } - n = nextn; - } - return offset + nextInt((int) n); - } - - /** - * Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound - * (exclusive). - * - * @param least - * the least value returned - * @param bound - * the upper bound (exclusive) - * @return the next value - * @throws IllegalArgumentException - * if least greater than or equal to bound - */ - public long nextLong(long least, long bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextLong(bound - least) + least; - } - - /** - * Returns a pseudorandom, uniformly distributed {@code double} value between 0 (inclusive) and the specified value - * (exclusive). - * - * @param n - * the bound on the random number to be returned. Must be positive. - * @return the next value - * @throws IllegalArgumentException - * if n is not positive - */ - public double nextDouble(double n) { - if (n <= 0) { - throw new IllegalArgumentException("n must be positive"); - } - return nextDouble() * n; - } - - /** - * Returns a pseudorandom, uniformly distributed value between the given least value (inclusive) and bound - * (exclusive). - * - * @param least - * the least value returned - * @param bound - * the upper bound (exclusive) - * @return the next value - * @throws IllegalArgumentException - * if least greater than or equal to bound - */ - public double nextDouble(double least, double bound) { - if (least >= bound) { - throw new IllegalArgumentException(); - } - return nextDouble() * (bound - least) + least; - } - - private static final long serialVersionUID = -5851777807851030925L; -} \ No newline at end of file diff --git a/core/src/main/java/com/taobao/arthas/core/util/metrics/RateCounter.java b/core/src/main/java/com/taobao/arthas/core/util/metrics/RateCounter.java index 38d4211536..659fdc9aa2 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/metrics/RateCounter.java +++ b/core/src/main/java/com/taobao/arthas/core/util/metrics/RateCounter.java @@ -2,8 +2,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLongArray; - -import com.taobao.arthas.core.util.ThreadLocalRandom; +import java.util.concurrent.ThreadLocalRandom; /** *


From dd10ba69d665bcb99ba5f9844abf43de090babe0 Mon Sep 17 00:00:00 2001
From: yanyir 
Date: Tue, 26 Sep 2023 15:05:35 +0800
Subject: [PATCH 2/3] Revert changes in Decompiler and StringUtils related to
 "\\R" handling

---
 .../taobao/arthas/core/util/Decompiler.java   | 19 +++++++----------
 .../taobao/arthas/core/util/StringUtils.java  | 21 -------------------
 2 files changed, 8 insertions(+), 32 deletions(-)

diff --git a/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java b/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java
index b6617bff0b..44baf75ea0 100644
--- a/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java
+++ b/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java
@@ -114,26 +114,23 @@ private static String addLineNumber(String src, Map lineMappin
 
         StringBuilder sb = new StringBuilder();
 
-        List lines = StringUtils.toLines(src);
+        String[] lines = src.split("\\R");
 
-        if (maxLineNumber >= 1000) {
-            formatStr = "/*%4d*/ ";
-            emptyStr = "         ";
-        } else if (maxLineNumber >= 100) {
+        if (maxLineNumber >= 100) {
             formatStr = "/*%3d*/ ";
             emptyStr = "        ";
+        } else if (maxLineNumber >= 1000) {
+            formatStr = "/*%4d*/ ";
+            emptyStr = "         ";
         }
-
-        int index = 0;
-        for (String line : lines) {
-            Integer srcLineNumber = lineMapping.get(index + 1);
+        for (int i = 0; i < lines.length; ++i) {
+            Integer srcLineNumber = lineMapping.get(i + 1);
             if (srcLineNumber != null) {
                 sb.append(String.format(formatStr, srcLineNumber));
             } else {
                 sb.append(emptyStr);
             }
-            sb.append(line).append("\n");
-            index++;
+            sb.append(lines[i]).append("\n");
         }
 
         return sb.toString();
diff --git a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java
index 58993479b5..dc7d663a60 100644
--- a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java
+++ b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java
@@ -909,27 +909,6 @@ public static String humanReadableByteCount(long bytes) {
                 : String.format("%.1f EiB", (bytes >> 20) / 0x1p40);
     }
 
-    public static List toLines(String text) {
-        List result = new ArrayList();
-        BufferedReader reader = new BufferedReader(new StringReader(text));
-        try {
-            String line = reader.readLine();
-            while (line != null) {
-                result.add(line);
-                line = reader.readLine();
-            }
-        } catch (IOException exc) {
-            // quit
-        } finally {
-            try {
-                reader.close();
-            } catch (IOException e) {
-                // ignore
-            }
-        }
-        return result;
-    }
-
     public static String randomString(int length) {
         StringBuilder sb = new StringBuilder(length);
         for (int i = 0; i < length; i++)

From ad4cd7db08a9e9138600c01679cd2341c54b5be2 Mon Sep 17 00:00:00 2001
From: yanyir 
Date: Tue, 24 Oct 2023 19:03:15 +0800
Subject: [PATCH 3/3] Revert "Revert changes in Decompiler and StringUtils
 related to "\\R" handling"

This reverts commit dd10ba69d665bcb99ba5f9844abf43de090babe0.
---
 .../taobao/arthas/core/util/Decompiler.java   | 19 ++++++++++-------
 .../taobao/arthas/core/util/StringUtils.java  | 21 +++++++++++++++++++
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java b/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java
index 44baf75ea0..b6617bff0b 100644
--- a/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java
+++ b/core/src/main/java/com/taobao/arthas/core/util/Decompiler.java
@@ -114,23 +114,26 @@ private static String addLineNumber(String src, Map lineMappin
 
         StringBuilder sb = new StringBuilder();
 
-        String[] lines = src.split("\\R");
+        List lines = StringUtils.toLines(src);
 
-        if (maxLineNumber >= 100) {
-            formatStr = "/*%3d*/ ";
-            emptyStr = "        ";
-        } else if (maxLineNumber >= 1000) {
+        if (maxLineNumber >= 1000) {
             formatStr = "/*%4d*/ ";
             emptyStr = "         ";
+        } else if (maxLineNumber >= 100) {
+            formatStr = "/*%3d*/ ";
+            emptyStr = "        ";
         }
-        for (int i = 0; i < lines.length; ++i) {
-            Integer srcLineNumber = lineMapping.get(i + 1);
+
+        int index = 0;
+        for (String line : lines) {
+            Integer srcLineNumber = lineMapping.get(index + 1);
             if (srcLineNumber != null) {
                 sb.append(String.format(formatStr, srcLineNumber));
             } else {
                 sb.append(emptyStr);
             }
-            sb.append(lines[i]).append("\n");
+            sb.append(line).append("\n");
+            index++;
         }
 
         return sb.toString();
diff --git a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java
index dc7d663a60..58993479b5 100644
--- a/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java
+++ b/core/src/main/java/com/taobao/arthas/core/util/StringUtils.java
@@ -909,6 +909,27 @@ public static String humanReadableByteCount(long bytes) {
                 : String.format("%.1f EiB", (bytes >> 20) / 0x1p40);
     }
 
+    public static List toLines(String text) {
+        List result = new ArrayList();
+        BufferedReader reader = new BufferedReader(new StringReader(text));
+        try {
+            String line = reader.readLine();
+            while (line != null) {
+                result.add(line);
+                line = reader.readLine();
+            }
+        } catch (IOException exc) {
+            // quit
+        } finally {
+            try {
+                reader.close();
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+        return result;
+    }
+
     public static String randomString(int length) {
         StringBuilder sb = new StringBuilder(length);
         for (int i = 0; i < length; i++)