Skip to content

Commit 8753f1b

Browse files
committed
Compartmentalise the parent loader.
1 parent 3061b72 commit 8753f1b

File tree

8 files changed

+68
-41
lines changed

8 files changed

+68
-41
lines changed

src/main/java/org/byteskript/skript/compiler/SimpleSkriptCompiler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,9 @@ public ElementTree assembleExpression(String expression, final Type expected, fi
263263
}
264264

265265
@Override
266+
@Deprecated
266267
public Class<?> load(byte[] bytecode, String name) {
267-
return Skript.LOADER.loadClass(name, bytecode);
268+
return Skript.currentLoader().loadClass(name, bytecode);
268269
}
269270

270271
@Override

src/main/java/org/byteskript/skript/lang/syntax/script/UnloadScriptEffect.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public static void unloadScript(Object object) throws IOException {
4444
else if (object instanceof Script script)
4545
Skript.localInstance().unloadScript(script);
4646
else if (object instanceof String name)
47-
Skript.localInstance().unloadScript(Skript.LOADER.findClass(name.replace('/', '.')));
47+
Skript.localInstance().unloadScript(Skript.localLoader().findClass(name.replace('/', '.')));
4848
}
4949

5050
}

src/main/java/org/byteskript/skript/lang/syntax/type/property/PropertyMember.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.byteskript.skript.api.syntax.Member;
1212
import org.byteskript.skript.compiler.*;
1313
import org.byteskript.skript.compiler.structure.SectionMeta;
14-
import org.byteskript.skript.error.ScriptError;
1514
import org.byteskript.skript.lang.element.StandardElements;
1615
import org.byteskript.skript.runtime.data.SourceData;
1716
import org.byteskript.skript.runtime.internal.ConsoleColour;

src/main/java/org/byteskript/skript/runtime/Skript.java

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ public final class Skript {
4141

4242
public static final ThreadGroup THREAD_GROUP = new ThreadGroup("skript");
4343
public static final int JAVA_VERSION = 61;
44-
public static final RuntimeClassLoader LOADER = new RuntimeClassLoader(Skript.class.getClassLoader());
4544
static final GlobalVariableMap VARIABLES = new GlobalVariableMap();
45+
private static final RuntimeClassLoader LOADER = new RuntimeClassLoader(Skript.class.getClassLoader());
4646
private static Skript skript;
4747
final ExecutorService executor;
4848
final SkriptThreadProvider factory;
@@ -51,12 +51,10 @@ public final class Skript {
5151
final ModifiableCompiler compiler;
5252
final List<OperationController> processes;
5353
final Map<Class<? extends Event>, EventHandler> events;
54-
final SkriptMirror mirror = new SkriptMirror(LOADER);
54+
final RuntimeClassLoader parent = new RuntimeClassLoader(LOADER);
5555
final WeakList<ScriptClassLoader> loaders = new WeakList<>();
5656
final List<Script> scripts = new ArrayList<>(); // the only strong reference, be careful!
5757

58-
//region Class Loaders
59-
6058
/**
6159
* Create a Skript runtime with a custom (non-default) Skript compiler.
6260
* This is used by the Jar-form script loader, which has no compiler.
@@ -101,6 +99,47 @@ public Skript() {
10199
this(new SkriptThreadProvider(), SkriptCompiler.createBasic(), Thread.currentThread());
102100
}
103101

102+
/**
103+
* Gets the parent class-loader local to this thread.
104+
* This is only usable from a script thread.
105+
*
106+
* @return the local runtime loader
107+
*/
108+
@ThreadSpecific
109+
public static RuntimeClassLoader localLoader() {
110+
final Thread current = Thread.currentThread();
111+
if (!(current instanceof ScriptThread thread))
112+
throw new ScriptRuntimeError("Not running on a script thread.");
113+
return thread.skript.parent;
114+
}
115+
116+
/**
117+
* Finds an arbitrary parent class-loader.
118+
* This will use the most recently-created Skript runtime.
119+
* This is unsafe, since it is unlikely to be the required loader.
120+
*
121+
* @return potentially null class-loader
122+
*/
123+
@Deprecated
124+
public static RuntimeClassLoader currentLoader() {
125+
return skript.parent;
126+
}
127+
128+
/**
129+
* Attempts to find the parent class-loader.
130+
* This will look for a local loader but default to the most-recently-created.
131+
* This is designed for internal use.
132+
*
133+
* @return an arbitrary class-loader
134+
*/
135+
@ThreadSpecific
136+
public static RuntimeClassLoader findLoader() {
137+
final Thread current = Thread.currentThread();
138+
if (current instanceof ScriptThread thread)
139+
return thread.skript.parent;
140+
return skript.parent;
141+
}
142+
104143
/**
105144
* This is the map of global `{!var}` variables.
106145
* This is a modifiable and atomic map.
@@ -114,7 +153,6 @@ public Skript() {
114153
public static GlobalVariableMap getVariables() {
115154
return VARIABLES;
116155
}
117-
//endregion
118156

119157
/**
120158
* This returns the Skript instance that launched the current thread.
@@ -157,8 +195,6 @@ private static String createClassName(String name, String path) {
157195
return path.substring(0, index).replace(File.separatorChar, '.');
158196
}
159197

160-
//region Runtime Instances
161-
162198
private static List<File> getFiles(List<File> files, Path root) {
163199
try (DirectoryStream<Path> stream = Files.newDirectoryStream(root)) {
164200
for (Path path : stream) {
@@ -175,6 +211,16 @@ private static List<File> getFiles(List<File> files, Path root) {
175211
return files;
176212
}
177213

214+
/**
215+
* Gets the parent class-loader attached to this Skript runtime.
216+
* This is used to search available libraries and scripts for classes.
217+
*
218+
* @return this runtime loader
219+
*/
220+
public RuntimeClassLoader getLoader() {
221+
return parent;
222+
}
223+
178224
/**
179225
* Submits this instruction to a background thread.
180226
* Background threads are safe for blocking.
@@ -195,9 +241,6 @@ public void runOnAsyncThread(final Instruction<?> runnable) {
195241
public Future<?> getOnAsyncThread(final Instruction<?> runnable) {
196242
return executor.submit(runnable::get);
197243
}
198-
//endregion
199-
200-
//region Thread Control
201244

202245
/**
203246
* Submits this instruction to a background thread.
@@ -232,9 +275,6 @@ public Script[] getScripts() {
232275
public Collection<OperationController> getProcesses() {
233276
return processes;
234277
}
235-
//endregion
236-
237-
//region Script Control
238278

239279
/**
240280
* Runs a script with a completing future.
@@ -353,9 +393,6 @@ private static Class<?> getClass(String name, Class<?> owner) {
353393
return null;
354394
}
355395
}
356-
//endregion
357-
358-
//region Libraries
359396

360397
/**
361398
* Registers a single class library, typically compiled from a script to load
@@ -378,7 +415,6 @@ public Class<?> defineClass(String name, byte[] bytes) {
378415
compiler.addLibrary(library);
379416
}
380417

381-
//region File Utilities
382418
private static String getClassName(InputStream is)
383419
throws IOException {
384420
final DataInputStream stream = new DataInputStream(is);
@@ -428,9 +464,6 @@ public boolean unregisterLibrary(Library library) {
428464
public ModifiableCompiler getCompiler() {
429465
return compiler;
430466
}
431-
//endregion
432-
433-
//region Script Compiling
434467

435468
/**
436469
* Returns an array of all registered libraries.
@@ -598,9 +631,6 @@ public void unloadScript(Class<?> main) {
598631
if (script.mainClass() == main) this.unloadScript(script);
599632
}
600633
}
601-
//endregion
602-
603-
//region Script Loading
604634

605635
/**
606636
* Unloads a script. This is a destructive operation.
@@ -845,9 +875,6 @@ public Script loadScript(final InputStream stream, final String name)
845875
throws IOException {
846876
return loadScript(this.loadClass(name, stream.readAllBytes()));
847877
}
848-
//endregion
849-
850-
//region Timings
851878

852879
/**
853880
* Loads a script from its compiled class file.
@@ -904,7 +931,6 @@ public ScheduledExecutorService getScheduler() {
904931
public ExecutorService getExecutor() {
905932
return executor;
906933
}
907-
//endregion
908934

909935
/**
910936
* Schedules a task to be run at some point in the future.
@@ -919,7 +945,7 @@ public Future<?> schedule(Runnable runnable, long millis) {
919945

920946
/**
921947
* This class handles the class-loading delegation for libraries and scripts.
922-
* It should not be interacted with directly, see {@link Skript#LOADER} for an instance.
948+
* It should not be interacted with directly, see {@link Skript#getLoader()} for an instance.
923949
*/
924950
public static class RuntimeClassLoader extends ClassLoader implements ClassProvider {
925951
protected RuntimeClassLoader(ClassLoader parent) {
@@ -987,6 +1013,5 @@ public Class<?> loadClass(String name, byte[] bytecode) {
9871013
return super.loadClass(name, bytecode);
9881014
}
9891015
}
990-
//endregion
9911016

9921017
}

src/main/java/org/byteskript/skript/runtime/internal/Member.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public Member(Script script, Method method, boolean async) {
3131
this.script = script;
3232
this.async = async;
3333
this.parameters = method.getParameterCount();
34-
final Mirror<?> mirror = Mirror.of(script.mainClass()).useProvider(Skript.LOADER);
34+
final Mirror<?> mirror = Mirror.of(script.mainClass()).useProvider(script.skriptInstance().getLoader());
3535
this.invoker = mirror.method(method);
3636
this.verifier = mirror.method(method.getName() + "_verify", method.getParameterTypes());
3737
}
@@ -79,7 +79,7 @@ else if (thing instanceof Future future)
7979
}
8080

8181
public static MethodAccessor<Object> findFunction(Object owner, String name) {
82-
return Mirror.of(owner).useProvider(Skript.LOADER).method(name);
82+
return Mirror.of(owner).useProvider(Skript.findLoader()).method(name);
8383
}
8484

8585
public static MethodAccessor<Object> getFunction(Object source, String pattern) {
@@ -120,7 +120,7 @@ private static int count(String pattern) {
120120
public static MethodAccessor<Object> findFunction(Object owner, String name, Number arguments) {
121121
final Class<?>[] parameters = new Class[arguments.intValue()];
122122
Arrays.fill(parameters, Object.class);
123-
return Mirror.of(owner).useProvider(Skript.LOADER).method(name, parameters);
123+
return Mirror.of(owner).useProvider(Skript.findLoader()).method(name, parameters);
124124
}
125125

126126
public Script getScript() {

src/main/java/org/byteskript/skript/runtime/internal/Metafactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ private static Method findTarget(MethodHandles.Lookup caller, String name, Class
5353
}
5454

5555
public static Object callFunction(String name, Object target, Object[] parameters) {
56-
final MethodAccessor<Object> accessor = Mirror.of(target).useProvider(Skript.LOADER).method(name, parameters);
56+
final MethodAccessor<Object> accessor = Mirror.of(target).useProvider(Skript.findLoader())
57+
.method(name, parameters);
5758
if (accessor == null) throw new ScriptRuntimeError("Unable to find function '" + name + "' from " + target);
5859
return accessor.invoke(parameters);
5960
}

src/main/java/org/byteskript/skript/runtime/internal/ScriptClassLoader.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class ScriptClassLoader extends ClassLoader implements ClassProvider {
1717
final List<Class<?>> loaded = new ArrayList<>();
1818

1919
public ScriptClassLoader() {
20-
super(Skript.LOADER);
20+
super(Skript.findLoader());
2121
}
2222

2323
public Class<?> loadClass0(String name) throws ClassNotFoundException {
@@ -32,15 +32,15 @@ public Class<?> loadClass(String name) throws ClassNotFoundException {
3232
for (final Class<?> thing : loaded) {
3333
if (thing.getName().equals(name)) return thing;
3434
}
35-
return Skript.LOADER.loadClass(name);
35+
return Skript.findLoader().loadClass(name);
3636
}
3737

3838
@Override
3939
public Class<?> findClass(String name) throws ClassNotFoundException {
4040
for (final Class<?> thing : loaded) {
4141
if (thing.getName().equals(name)) return thing;
4242
}
43-
return Skript.LOADER.findClass(name);
43+
return Skript.findLoader().findClass(name);
4444
}
4545

4646
public Class<?> findClass0(String name) throws ClassNotFoundException {

src/main/java/skript.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,11 @@ public static MethodAccessor<Object> get_java_method(Object owner, Object name,
192192
private static Mirror<?> mirror(Object owner) {
193193
if (owner == null) return null;
194194
if (owner instanceof Class<?> type) {
195-
if (type.getName().startsWith("skript")) return Mirror.of(type).useProvider(Skript.LOADER);
195+
if (type.getName().startsWith("skript")) return Mirror.of(type).useProvider(Skript.findLoader());
196196
return Mirror.of(type);
197197
} else {
198-
if (owner.getClass().getName().startsWith("skript")) return Mirror.of(owner).useProvider(Skript.LOADER);
198+
if (owner.getClass().getName().startsWith("skript"))
199+
return Mirror.of(owner).useProvider(Skript.findLoader());
199200
return Mirror.of(owner);
200201
}
201202
}

0 commit comments

Comments
 (0)