From d4022743f3e1d5c328602009a509dc6f673a444d Mon Sep 17 00:00:00 2001 From: "J.Bachorik" Date: Sun, 26 Aug 2018 21:09:02 +0200 Subject: [PATCH 1/2] Use lazy inited regex expression for template extraction (#363) Fixes #345 --- src/share/classes/com/sun/btrace/ArgsMap.java | 70 +++++-------------- src/test/java/com/sun/btrace/ArgsMapTest.java | 55 +++++++++++++++ 2 files changed, 71 insertions(+), 54 deletions(-) create mode 100644 src/test/java/com/sun/btrace/ArgsMapTest.java diff --git a/src/share/classes/com/sun/btrace/ArgsMap.java b/src/share/classes/com/sun/btrace/ArgsMap.java index c1b2c2da7..adf2ce08e 100644 --- a/src/share/classes/com/sun/btrace/ArgsMap.java +++ b/src/share/classes/com/sun/btrace/ArgsMap.java @@ -24,11 +24,18 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * A simple argument map wrapper allowing indexed access */ -public final class ArgsMap implements Iterable>{ +public final class ArgsMap implements Iterable> { + private static final class PatternSingleton { + // lazy initialization trick + // do not compile the pattern until it is actually requested + private static final Pattern INSTANCE = Pattern.compile("\\$\\{(.*?)\\}"); + } private final LinkedHashMap map; private final DebugSupport debug; @@ -138,60 +145,15 @@ public String template(String value) { return value; } - StringBuilder sb = new StringBuilder(); - StringBuilder keySb = new StringBuilder(); - int state = 0; - - for (char c : value.toCharArray()) { - switch (c) { - case '$': { - if (state == 0) { - state = 1; - } - break; - } - case '{': { - if (state == 1) { - state = 2; - keySb.setLength(0); - } - break; - } - case '}': { - if (state == 2) { - String key = keySb.toString(); - String val = get(key); - if (val != null) { - sb.append(val); - } else { - sb.append("${").append(key).append("}"); - } - state = 0; - } - break; - } - default: { - switch (state) { - case 0: { - sb.append(c); - break; - } - case 2: { - keySb.append(c); - break; - } - default: { - // other states are invalid; ignore input - } - } - } - } - } + Matcher matcher = PatternSingleton.INSTANCE.matcher(value); + StringBuffer buffer = new StringBuffer(value.length()); - String expanded = sb.toString(); - if (debug.isDebug()) { - debug.debug("Template: " + value + " -> " + expanded); + while (matcher.find()) { + String val = get(matcher.group(1)); + matcher.appendReplacement(buffer, val != null ? val : "$0"); } - return expanded; + matcher.appendTail(buffer); + + return buffer.toString(); } } diff --git a/src/test/java/com/sun/btrace/ArgsMapTest.java b/src/test/java/com/sun/btrace/ArgsMapTest.java new file mode 100644 index 000000000..99673203a --- /dev/null +++ b/src/test/java/com/sun/btrace/ArgsMapTest.java @@ -0,0 +1,55 @@ +package com.sun.btrace; + +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ArgsMapTest { + private static final String KEY1 = "key1"; + private static final String KEY2 = "key2"; + private static final String VALUE1 = "value1"; + private static final String VALUE2 = "value2"; + + private ArgsMap instance; + + @Before + public void setUp() { + instance = new ArgsMap(); + instance.put(KEY1, VALUE1); + instance.put(KEY2, VALUE2); + } + + @Test + public void templateExisting() { + String value = instance.template(KEY1 + "=${" + KEY1 + "}"); + assertEquals(KEY1 + "=" + VALUE1, value); + } + + @Test + public void templateNonExisting() { + String orig = KEY1 + "=${key3}"; + String value = instance.template(orig); + assertEquals(orig, value); + } + + @Test + public void templateTrailing$() { + String orig = KEY1 + "$"; + String value = instance.template(orig); + assertEquals(orig, value); + } + + @Test + public void templateUnclosedPlaceholder() { + String orig = KEY1 + "${"; + String value = instance.template(orig); + assertEquals(orig, value); + } + + @Test + public void templateSingle$() { + String orig = KEY1 + "$" + KEY2; + String value = instance.template(orig); + assertEquals(orig, value); + } +} From 707b3116eca0431b8e3cbd1cf00de9cf06425b48 Mon Sep 17 00:00:00 2001 From: refactormachine <39365897+refactormachine@users.noreply.github.com> Date: Sun, 26 Aug 2018 22:11:36 +0300 Subject: [PATCH 2/2] Refactored BtraceTaskImpl (#362) --- .../btrace/api/impl/BTraceTaskDispatcher.java | 89 +++++++++++++++++++ .../sun/btrace/api/impl/BTraceTaskImpl.java | 60 +------------ 2 files changed, 93 insertions(+), 56 deletions(-) create mode 100644 src/share/classes/com/sun/btrace/api/impl/BTraceTaskDispatcher.java diff --git a/src/share/classes/com/sun/btrace/api/impl/BTraceTaskDispatcher.java b/src/share/classes/com/sun/btrace/api/impl/BTraceTaskDispatcher.java new file mode 100644 index 000000000..1ea1a4fb2 --- /dev/null +++ b/src/share/classes/com/sun/btrace/api/impl/BTraceTaskDispatcher.java @@ -0,0 +1,89 @@ +package com.sun.btrace.api.impl; + +import com.sun.btrace.api.BTraceTask; +import com.sun.btrace.comm.*; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +class BTraceTaskDispatcher { + private final static ExecutorService dispatcher = Executors.newSingleThreadExecutor(); + private final Set messageDispatchers = new HashSet<>(); + + BTraceTaskDispatcher() { + } + + /** + * Dispatcher management + * + * @param dispatcher {@linkplain BTraceTask.MessageDispatcher} instance to add + */ + void addMessageDispatcher(BTraceTask.MessageDispatcher dispatcher) { + synchronized (messageDispatchers) { + messageDispatchers.add(dispatcher); + } + } + + /** + * Dispatcher management + * + * @param dispatcher {@linkplain BTraceTask.MessageDispatcher} instance to remove + */ + void removeMessageDispatcher(BTraceTask.MessageDispatcher dispatcher) { + synchronized (messageDispatchers) { + messageDispatchers.remove(dispatcher); + } + } + + @SuppressWarnings("FutureReturnValueIgnored") + void dispatchCommand(final Command cmd) { + final Set dispatchingSet = new HashSet(); + synchronized (messageDispatchers) { + dispatchingSet.addAll(messageDispatchers); + } + dispatcher.submit(new Runnable() { + @Override + public void run() { + for (BTraceTask.MessageDispatcher listener : dispatchingSet) { + switch (cmd.getType()) { + case Command.MESSAGE: { + listener.onPrintMessage(((MessageCommand) cmd).getMessage()); + break; + } + case Command.RETRANSFORM_CLASS: { + listener.onClassInstrumented(((RetransformClassNotification) cmd).getClassName()); + break; + } + case Command.NUMBER: { + NumberDataCommand ndc = (NumberDataCommand) cmd; + listener.onNumberMessage(ndc.getName(), ndc.getValue()); + break; + } + case Command.NUMBER_MAP: { + NumberMapDataCommand nmdc = (NumberMapDataCommand) cmd; + listener.onNumberMap(nmdc.getName(), nmdc.getData()); + break; + } + case Command.STRING_MAP: { + StringMapDataCommand smdc = (StringMapDataCommand) cmd; + listener.onStringMap(smdc.getName(), smdc.getData()); + break; + } + case Command.GRID_DATA: { + GridDataCommand gdc = (GridDataCommand) cmd; + listener.onGrid(gdc.getName(), gdc.getData()); + break; + } + case Command.ERROR: { + ErrorCommand ec = (ErrorCommand) cmd; + listener.onError(ec.getCause()); + break; + } + } + } + } + }); + } +} \ No newline at end of file diff --git a/src/share/classes/com/sun/btrace/api/impl/BTraceTaskImpl.java b/src/share/classes/com/sun/btrace/api/impl/BTraceTaskImpl.java index 31c290a0e..b1fb5d9a1 100644 --- a/src/share/classes/com/sun/btrace/api/impl/BTraceTaskImpl.java +++ b/src/share/classes/com/sun/btrace/api/impl/BTraceTaskImpl.java @@ -32,8 +32,6 @@ import java.util.EnumSet; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -51,9 +49,8 @@ public class BTraceTaskImpl extends BTraceTask implements BTraceEngineImpl.State final private AtomicReference currentState = new AtomicReference<>(State.NEW); final private Set stateListeners = new HashSet<>(); - final private Set messageDispatchers = new HashSet<>(); - final private static ExecutorService dispatcher = Executors.newSingleThreadExecutor(); + private final BTraceTaskDispatcher taskDispatcher = new BTraceTaskDispatcher(); private String script; private int numInstrClasses; @@ -174,9 +171,7 @@ public void removeStateListener(StateListener listener) { */ @Override public void addMessageDispatcher(MessageDispatcher dispatcher) { - synchronized (messageDispatchers) { - messageDispatchers.add(dispatcher); - } + taskDispatcher.addMessageDispatcher(dispatcher); } /** @@ -185,9 +180,7 @@ public void addMessageDispatcher(MessageDispatcher dispatcher) { */ @Override public void removeMessageDispatcher(MessageDispatcher dispatcher) { - synchronized (messageDispatchers) { - messageDispatchers.remove(dispatcher); - } + taskDispatcher.removeMessageDispatcher(dispatcher); } /** @@ -272,52 +265,7 @@ private void fireStateChange() { @SuppressWarnings("FutureReturnValueIgnored") void dispatchCommand(final Command cmd) { - final Set dispatchingSet = new HashSet(); - synchronized(messageDispatchers) { - dispatchingSet.addAll(messageDispatchers); - } - dispatcher.submit(new Runnable() { - @Override - public void run() { - for(MessageDispatcher listener : dispatchingSet) { - switch (cmd.getType()) { - case Command.MESSAGE: { - listener.onPrintMessage(((MessageCommand)cmd).getMessage()); - break; - } - case Command.RETRANSFORM_CLASS: { - listener.onClassInstrumented(((RetransformClassNotification)cmd).getClassName()); - break; - } - case Command.NUMBER: { - NumberDataCommand ndc = (NumberDataCommand)cmd; - listener.onNumberMessage(ndc.getName(), ndc.getValue()); - break; - } - case Command.NUMBER_MAP: { - NumberMapDataCommand nmdc = (NumberMapDataCommand)cmd; - listener.onNumberMap(nmdc.getName(), nmdc.getData()); - break; - } - case Command.STRING_MAP: { - StringMapDataCommand smdc = (StringMapDataCommand)cmd; - listener.onStringMap(smdc.getName(), smdc.getData()); - break; - } - case Command.GRID_DATA: { - GridDataCommand gdc = (GridDataCommand)cmd; - listener.onGrid(gdc.getName(), gdc.getData()); - break; - } - case Command.ERROR: { - ErrorCommand ec = (ErrorCommand)cmd; - listener.onError(ec.getCause()); - break; - } - } - } - } - }); + taskDispatcher.dispatchCommand(cmd); } @Override