aboutsummaryrefslogtreecommitdiff
path: root/spark-common/src
diff options
context:
space:
mode:
authorLuck <git@lucko.me>2024-07-18 18:13:46 +0100
committerLuck <git@lucko.me>2024-07-18 18:13:46 +0100
commited8eac595c26719571683cff7f3c9de2cfc28406 (patch)
treec23428d3539e6c315d89409094c001db057ba8cd /spark-common/src
parent1b75abc56cdf01962b618e1f81d39c91558d2666 (diff)
downloadspark-ed8eac595c26719571683cff7f3c9de2cfc28406.tar.gz
spark-ed8eac595c26719571683cff7f3c9de2cfc28406.tar.bz2
spark-ed8eac595c26719571683cff7f3c9de2cfc28406.zip
Refactor ClassFinder into interface
Diffstat (limited to 'spark-common/src')
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java5
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java15
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java2
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java6
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/sampler/async/AsyncSampler.java2
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/sampler/java/JavaSampler.java2
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/sampler/source/ClassSourceLookup.java12
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/MethodDisambiguator.java10
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/classfinder/ClassFinder.java46
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/classfinder/CombinedClassFinder.java44
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/classfinder/FallbackClassFinder.java40
-rw-r--r--spark-common/src/main/java/me/lucko/spark/common/util/classfinder/InstrumentationClassFinder.java (renamed from spark-common/src/main/java/me/lucko/spark/common/util/ClassFinder.java)32
12 files changed, 183 insertions, 33 deletions
diff --git a/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java b/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java
index 21f9210..733510d 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/SparkPlatform.java
@@ -55,6 +55,7 @@ import me.lucko.spark.common.util.BytebinClient;
import me.lucko.spark.common.util.Configuration;
import me.lucko.spark.common.util.SparkStaticLogger;
import me.lucko.spark.common.util.TemporaryFiles;
+import me.lucko.spark.common.util.classfinder.ClassFinder;
import me.lucko.spark.common.ws.TrustedKeyStore;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
@@ -285,6 +286,10 @@ public class SparkPlatform {
return this.plugin.createClassSourceLookup();
}
+ public ClassFinder createClassFinder() {
+ return this.plugin.createClassFinder();
+ }
+
public TickStatistics getTickStatistics() {
return this.tickStatistics;
}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java b/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java
index a3bdceb..bf745df 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/SparkPlugin.java
@@ -33,6 +33,9 @@ import me.lucko.spark.common.sampler.source.ClassSourceLookup;
import me.lucko.spark.common.sampler.source.SourceMetadata;
import me.lucko.spark.common.tick.TickHook;
import me.lucko.spark.common.tick.TickReporter;
+import me.lucko.spark.common.util.classfinder.ClassFinder;
+import me.lucko.spark.common.util.classfinder.FallbackClassFinder;
+import me.lucko.spark.common.util.classfinder.InstrumentationClassFinder;
import java.nio.file.Path;
import java.util.Collection;
@@ -150,6 +153,18 @@ public interface SparkPlugin {
}
/**
+ * Creates a class finder for the platform.
+ *
+ * @return the class finder
+ */
+ default ClassFinder createClassFinder() {
+ return ClassFinder.combining(
+ new InstrumentationClassFinder(this),
+ FallbackClassFinder.INSTANCE
+ );
+ }
+
+ /**
* Gets a list of known sources (plugins/mods) on the platform.
*
* @return a list of sources
diff --git a/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java b/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java
index 9ce66dc..9e2647a 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/command/modules/SamplerModule.java
@@ -507,7 +507,7 @@ public class SamplerModule implements CommandModule {
.creator(resp.senderData())
.comment(Iterables.getFirst(arguments.stringFlag("comment"), null))
.mergeMode(() -> {
- MethodDisambiguator methodDisambiguator = new MethodDisambiguator();
+ MethodDisambiguator methodDisambiguator = new MethodDisambiguator(platform.createClassFinder());
return arguments.boolFlag("separate-parent-calls")
? MergeMode.separateParentCalls(methodDisambiguator)
: MergeMode.sameMethod(methodDisambiguator);
diff --git a/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java b/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java
index 445702e..8a9c05f 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/sampler/AbstractSampler.java
@@ -32,6 +32,7 @@ import me.lucko.spark.common.sampler.source.ClassSourceLookup;
import me.lucko.spark.common.sampler.source.SourceMetadata;
import me.lucko.spark.common.sampler.window.ProtoTimeEncoder;
import me.lucko.spark.common.sampler.window.WindowStatisticsCollector;
+import me.lucko.spark.common.util.classfinder.ClassFinder;
import me.lucko.spark.common.ws.ViewerSocket;
import me.lucko.spark.proto.SparkProtos;
import me.lucko.spark.proto.SparkSamplerProtos.SamplerData;
@@ -44,6 +45,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Supplier;
/**
* Base implementation class for {@link Sampler}s.
@@ -230,11 +232,11 @@ public abstract class AbstractSampler implements Sampler {
proto.setMetadata(metadata);
}
- protected void writeDataToProto(SamplerData.Builder proto, DataAggregator dataAggregator, MergeMode mergeMode, ClassSourceLookup classSourceLookup) {
+ protected void writeDataToProto(SamplerData.Builder proto, DataAggregator dataAggregator, MergeMode mergeMode, ClassSourceLookup classSourceLookup, Supplier<ClassFinder> classFinderSupplier) {
List<ThreadNode> data = dataAggregator.exportData();
data.sort(Comparator.comparing(ThreadNode::getThreadLabel));
- ClassSourceLookup.Visitor classSourceVisitor = ClassSourceLookup.createVisitor(classSourceLookup);
+ ClassSourceLookup.Visitor classSourceVisitor = ClassSourceLookup.createVisitor(classSourceLookup, classFinderSupplier);
ProtoTimeEncoder timeEncoder = new ProtoTimeEncoder(getMode().valueTransformer(), data);
int[] timeWindows = timeEncoder.getKeys();
diff --git a/spark-common/src/main/java/me/lucko/spark/common/sampler/async/AsyncSampler.java b/spark-common/src/main/java/me/lucko/spark/common/sampler/async/AsyncSampler.java
index e3470b4..5350558 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/sampler/async/AsyncSampler.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/sampler/async/AsyncSampler.java
@@ -221,7 +221,7 @@ public class AsyncSampler extends AbstractSampler {
proto.setChannelInfo(exportProps.channelInfo());
}
writeMetadataToProto(proto, platform, exportProps.creator(), exportProps.comment(), this.dataAggregator);
- writeDataToProto(proto, this.dataAggregator, exportProps.mergeMode().get(), exportProps.classSourceLookup().get());
+ writeDataToProto(proto, this.dataAggregator, exportProps.mergeMode().get(), exportProps.classSourceLookup().get(), platform::createClassFinder);
return proto.build();
}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/sampler/java/JavaSampler.java b/spark-common/src/main/java/me/lucko/spark/common/sampler/java/JavaSampler.java
index bae7e19..e3ae73a 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/sampler/java/JavaSampler.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/sampler/java/JavaSampler.java
@@ -193,7 +193,7 @@ public class JavaSampler extends AbstractSampler implements Runnable {
proto.setChannelInfo(exportProps.channelInfo());
}
writeMetadataToProto(proto, platform, exportProps.creator(), exportProps.comment(), this.dataAggregator);
- writeDataToProto(proto, this.dataAggregator, exportProps.mergeMode().get(), exportProps.classSourceLookup().get());
+ writeDataToProto(proto, this.dataAggregator, exportProps.mergeMode().get(), exportProps.classSourceLookup().get(), platform::createClassFinder);
return proto.build();
}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/sampler/source/ClassSourceLookup.java b/spark-common/src/main/java/me/lucko/spark/common/sampler/source/ClassSourceLookup.java
index a62f8d1..c856123 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/sampler/source/ClassSourceLookup.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/sampler/source/ClassSourceLookup.java
@@ -23,7 +23,7 @@ package me.lucko.spark.common.sampler.source;
import me.lucko.spark.common.SparkPlatform;
import me.lucko.spark.common.sampler.node.StackTraceNode;
import me.lucko.spark.common.sampler.node.ThreadNode;
-import me.lucko.spark.common.util.ClassFinder;
+import me.lucko.spark.common.util.classfinder.ClassFinder;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.IOException;
@@ -42,6 +42,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.function.Function;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
@@ -203,11 +204,11 @@ public interface ClassSourceLookup {
Map<String, String> getLineSourceMapping();
}
- static Visitor createVisitor(ClassSourceLookup lookup) {
+ static Visitor createVisitor(ClassSourceLookup lookup, Supplier<ClassFinder> classFinderSupplier) {
if (lookup == ClassSourceLookup.NO_OP) {
return NoOpVisitor.INSTANCE; // don't bother!
}
- return new VisitorImpl(lookup);
+ return new VisitorImpl(lookup, classFinderSupplier.get());
}
enum NoOpVisitor implements Visitor {
@@ -254,14 +255,15 @@ public interface ClassSourceLookup {
*/
class VisitorImpl implements Visitor {
private final ClassSourceLookup lookup;
- private final ClassFinder classFinder = new ClassFinder();
+ private final ClassFinder classFinder;
private final SourcesMap<String> classSources = new SourcesMap<>(Function.identity());
private final SourcesMap<MethodCall> methodSources = new SourcesMap<>(MethodCall::toString);
private final SourcesMap<MethodCallByLine> lineSources = new SourcesMap<>(MethodCallByLine::toString);
- VisitorImpl(ClassSourceLookup lookup) {
+ VisitorImpl(ClassSourceLookup lookup, ClassFinder classFinder) {
this.lookup = lookup;
+ this.classFinder = classFinder;
}
@Override
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/MethodDisambiguator.java b/spark-common/src/main/java/me/lucko/spark/common/util/MethodDisambiguator.java
index 2b2e3c7..3b0ddc3 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/util/MethodDisambiguator.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/MethodDisambiguator.java
@@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import me.lucko.spark.common.sampler.node.StackTraceNode;
+import me.lucko.spark.common.util.classfinder.ClassFinder;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
@@ -43,8 +44,13 @@ import java.util.concurrent.ConcurrentHashMap;
* to a method (method name + method description).
*/
public final class MethodDisambiguator {
- private final Map<String, ComputedClass> cache = new ConcurrentHashMap<>();
- private final ClassFinder classFinder = new ClassFinder();
+ private final ClassFinder classFinder;
+ private final Map<String, ComputedClass> cache;
+
+ public MethodDisambiguator(ClassFinder classFinder) {
+ this.classFinder = classFinder;
+ this.cache = new ConcurrentHashMap<>();
+ }
public Optional<MethodDescription> disambiguate(StackTraceNode element) {
String desc = element.getMethodDescription();
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/ClassFinder.java b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/ClassFinder.java
new file mode 100644
index 0000000..1ee75c6
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/ClassFinder.java
@@ -0,0 +1,46 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.util.classfinder;
+
+import com.google.common.collect.ImmutableList;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public interface ClassFinder {
+
+ /**
+ * Creates a ClassFinder that combines the results of multiple other finders.
+ *
+ * @param finders the other class finders
+ * @return the combined class finder
+ */
+ static ClassFinder combining(ClassFinder... finders) {
+ return new CombinedClassFinder(ImmutableList.copyOf(finders));
+ }
+
+ /**
+ * Attempts to find a class by name.
+ *
+ * @param className the name of the class
+ * @return the class, if found
+ */
+ @Nullable Class<?> findClass(String className);
+
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/CombinedClassFinder.java b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/CombinedClassFinder.java
new file mode 100644
index 0000000..ed63f36
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/CombinedClassFinder.java
@@ -0,0 +1,44 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.util.classfinder;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+class CombinedClassFinder implements ClassFinder {
+ private final List<ClassFinder> finders;
+
+ CombinedClassFinder(List<ClassFinder> finders) {
+ this.finders = finders;
+ }
+
+ @Override
+ public @Nullable Class<?> findClass(String className) {
+ for (ClassFinder finder : this.finders) {
+ Class<?> clazz = finder.findClass(className);
+ if (clazz != null) {
+ return clazz;
+ }
+ }
+ return null;
+ }
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/FallbackClassFinder.java b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/FallbackClassFinder.java
new file mode 100644
index 0000000..dd3c9f0
--- /dev/null
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/FallbackClassFinder.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of spark.
+ *
+ * Copyright (c) lucko (Luck) <luck@lucko.me>
+ * Copyright (c) contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package me.lucko.spark.common.util.classfinder;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * Uses {@link Class#forName(String)} to find a class reference for given class names.
+ */
+public enum FallbackClassFinder implements ClassFinder {
+ INSTANCE;
+
+ @Override
+ public @Nullable Class<?> findClass(String className) {
+ try {
+ return Class.forName(className);
+ } catch (Throwable e) {
+ return null;
+ }
+ }
+
+}
diff --git a/spark-common/src/main/java/me/lucko/spark/common/util/ClassFinder.java b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/InstrumentationClassFinder.java
index cead938..5f06d64 100644
--- a/spark-common/src/main/java/me/lucko/spark/common/util/ClassFinder.java
+++ b/spark-common/src/main/java/me/lucko/spark/common/util/classfinder/InstrumentationClassFinder.java
@@ -18,8 +18,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package me.lucko.spark.common.util;
+package me.lucko.spark.common.util.classfinder;
+import me.lucko.spark.common.SparkPlugin;
+import me.lucko.spark.common.util.JavaVersion;
import net.bytebuddy.agent.ByteBuddyAgent;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -33,18 +35,18 @@ import java.util.logging.Level;
*
* <p>This is necessary as we don't always have access to the classloader for a given class.</p>
*/
-public class ClassFinder {
+public class InstrumentationClassFinder implements ClassFinder {
private static boolean warned = false;
- private static Instrumentation loadInstrumentation() {
+ private static Instrumentation loadInstrumentation(SparkPlugin plugin) {
Instrumentation instrumentation = null;
try {
instrumentation = ByteBuddyAgent.install();
if (!warned && JavaVersion.getJavaVersion() >= 21) {
warned = true;
- SparkStaticLogger.log(Level.INFO, "If you see a warning above that says \"WARNING: A Java agent has been loaded dynamically\", it can be safely ignored.");
- SparkStaticLogger.log(Level.INFO, "See here for more information: https://spark.lucko.me/docs/misc/Java-agent-warning");
+ plugin.log(Level.INFO, "If you see a warning above that says \"WARNING: A Java agent has been loaded dynamically\", it can be safely ignored.");
+ plugin.log(Level.INFO, "See here for more information: https://spark.lucko.me/docs/misc/Java-agent-warning");
}
} catch (Exception e) {
// ignored
@@ -54,8 +56,8 @@ public class ClassFinder {
private final Map<String, Class<?>> classes = new HashMap<>();
- public ClassFinder() {
- Instrumentation instrumentation = loadInstrumentation();
+ public InstrumentationClassFinder(SparkPlugin plugin) {
+ Instrumentation instrumentation = loadInstrumentation(plugin);
if (instrumentation == null) {
return;
}
@@ -66,21 +68,9 @@ public class ClassFinder {
}
}
+ @Override
public @Nullable Class<?> findClass(String className) {
- // try instrumentation
- Class<?> clazz = this.classes.get(className);
- if (clazz != null) {
- return clazz;
- }
-
- // try Class.forName
- try {
- return Class.forName(className);
- } catch (Throwable e) {
- // ignore
- }
-
- return null;
+ return this.classes.get(className);
}
}