Closed deathcap closed 10 years ago
Looks like the problem is:
this_class: 'Lorg/bukkit/configuration/serialization/ConfigurationSerializable;',
edit: actually, the dynamically loaded plugin class MyPlugin. added to src/ClassData.ts
public get_interfaces(): ReferenceClassData[] {
if(this.interface_cdatas===undefined)console.log('ABOUT TO RETURN undefined cdatas for',this);
return this.interface_cdatas;
}
logs:
ABOUT TO RETURN undefined cdatas for {
…
this_class: 'LMyPlugin;',
super_class: 'Lorg/bukkit/plugin/java/JavaPlugin;',
interfaces: [],
fields: [],
fl_cache: {},
methods:
{ '<init>()V':
{ cls: [Circular],
idx: 0,
access_byte: 1,
access_flags: [Object],
name: '<init>',
raw_descriptor: '()V',
reset_caches: false,
param_types: [],
param_bytes: 1,
num_args: 1,
return_type: 'V',
attrs: [Object],
code: [Object] },
'onEnable()V':
{ cls: [Circular],
idx: 1,
access_byte: 1,
access_flags: [Object],
name: 'onEnable',
raw_descriptor: '()V',
reset_caches: false,
param_types: [],
param_bytes: 1,
num_args: 1,
return_type: 'V',
attrs: [Object],
code: [Object] } },
ml_cache: {},
attrs: [ { name: 'SourceFile', filename: 'MyPlugin.java' } ],
The interface_cdatas
property is not only undefined
, but it does not exist on this
('interface_cdatas' in this === false). It is supposed to be set in setResolved()
—but this isn't called.
The class is checked for in is_subinterface
before it is resolved.
Bukkit dynamically loads the plugin class through its own class loader in https://github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java#L40:
jarClass = Class.forName(description.getMain(), true, this);
where true=initialize, this=the custom classloader PluginClassLoader
. It then tries to cast it:
pluginClass = jarClass.asSubclass(JavaPlugin.class);
which fails because the class hasn't been resolved yet, much less initialized. The ClassState state enum for the class with undefined interface_cdatas is 1 = loaded (not yet 2=resolved, or 3=initialized). Might be a problem when initializing classes loaded via custom loaders.
there is a classes/test/CustomClassLoader test case in doppio, using the same Class.forName(s,true,loader1)
method (to load classes.test.CustomClassLoader through itself), and also CustomClassLoader2. Neither seem to hit this problem.
Correction: the line of Java code which causes the doppio crash is in https://github.com/Bukkit/Bukkit/blob/master/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java#L201
void setClass(final String name, final Class<?> clazz) {
if (!classes.containsKey(name)) {
classes.put(name, clazz);
if (ConfigurationSerializable.class.isAssignableFrom(clazz)) { // <-- here ***
Class<? extends ConfigurationSerializable> serializable = clazz.asSubclass(ConfigurationSerializable.class);
ConfigurationSerialization.registerClass(serializable);
}
}
}
setClass is called by PluginClassLoader's findClass. So the isAssignableFrom() call happens right after the class is defined, before it is "resolved".
--- a/classes/test/CustomClassLoader2.java
+++ b/classes/test/CustomClassLoader2.java
@@ -63,6 +63,7 @@ public class CustomClassLoader2 extends ClassLoader {
result = defineClass(className,classByte,0,classByte.length,null);
System.out.println("Registering class " + className);
classes.put(className,result);
+ System.out.println("isAssignableFrom = " + String.class.isAssignableFrom(result));
System.out.println("Found class. Returning.");
return result;
} catch(Exception e){
result in doppio (ok in oracle jvm):
doppio $ ./doppio-dev classes/test/CustomClassLoader2
Loading Dog...
Loading class classes.test.Dog
Finding class classes.test.Dog
Defining class classes.test.Dog
Registering class classes.test.Dog
isAssignableFrom = false
Found class. Returning.
Dog's methods
Loading class java.lang.String
Finding class java.lang.String
Couldn't get the class ourselves!
Getting the system class.
TypeError: Cannot call method 'map' of undefined
at Method.java_lang_Class.getInterfaces()[Ljava/lang/Class; [as code] (eval at <anonymous> (/Users/admin/games/voxeljs/doppio/build/dev-cli/src/jvm.ts:296:17), <anonymous>:151:33)
at code (/Users/admin/games/voxeljs/doppio/build/dev-cli/src/methods.ts:284:22)
at NativeStackFrame.run (/Users/admin/games/voxeljs/doppio/build/dev-cli/src/threading.ts:233:37)
at JVMThread.run (/Users/admin/games/voxeljs/doppio/build/dev-cli/src/threading.ts:568:31)
at JVMThread.setStatus (/Users/admin/games/voxeljs/doppio/build/dev-cli/src/threading.ts:652:16)
at Object._onImmediate (/Users/admin/games/voxeljs/doppio/build/dev-cli/src/threading.ts:393:24)
at processImmediate [as _immediateCallback] (timers.js:330:15)
Isolated and opened a doppio issue: https://github.com/plasma-umass/doppio/issues/313
Interestingly, the isolated test case succeeds on their master branch, only fails on natives_refactor, but master hits https://github.com/deathcap/Junket/issues/1 so I can't use it, but hopefully this will help track down the problem.
Thinking how I might be able to workaround this on my side.. if I comment out the ConfigurationSerializable check in Bukkit:
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
index b178c0d..d85bc6b 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -202,10 +202,12 @@ public final class JavaPluginLoader implements PluginLoader {
if (!classes.containsKey(name)) {
classes.put(name, clazz);
+ /* workaround https://github.com/deathcap/Junket/issues/2
if (ConfigurationSerializable.class.isAssignableFrom(clazz)) {
Class<? extends ConfigurationSerializable> serializable = clazz.asSubclass(ConfigurationSerializable.class);
ConfigurationSerialization.registerClass(serializable);
}
+ */
}
}
then it works! The sample plugin loads and runs:
+ java -jar build/distributions/Junket-0.0.1-shadow.jar
Hello
May 15, 2014 7:25:05 PM deathcap.junket.Server <init>
INFO: Starting up...
May 15, 2014 7:25:05 PM deathcap.junket.Server <init>
INFO: Loaded 1 plugins
May 15, 2014 7:25:05 PM deathcap.junket.Server <init>
INFO: Enabling plugin MyPlugin vv5cd2e67
May 15, 2014 7:25:05 PM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Enabling MyPlugin vv5cd2e67
May 15, 2014 7:25:05 PM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Hello, plugin!
+ ../doppio/doppio-dev -jar build/distributions/Junket-0.0.1-shadow.jar
Hello
May 16, 2014 2:25:09 AM deathcap.junket.Server <init>
INFO: Starting up...
May 16, 2014 2:25:27 AM deathcap.junket.Server <init>
INFO: Loaded 1 plugins
May 16, 2014 2:25:27 AM deathcap.junket.Server <init>
INFO: Enabling plugin MyPlugin vv5cd2e67
May 16, 2014 2:25:27 AM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Enabling MyPlugin vv5cd2e67
May 16, 2014 2:25:27 AM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Hello, plugin!
but, would like to avoid changes to the Bukkit dependency if possible.
Fixed in doppio as of https://github.com/plasma-umass/doppio/commit/44b137a49df7dc8efaa39abd0c67526d904e79bf - can now load plugins with the native Bukkit API:
+ java -jar build/distributions/Junket-0.0.1-shadow.jar
Hello
May 16, 2014 12:26:35 PM deathcap.junket.Server <init>
INFO: Starting up...
May 16, 2014 12:26:35 PM deathcap.junket.Server <init>
INFO: Loaded 1 plugins
May 16, 2014 12:26:35 PM deathcap.junket.Server <init>
INFO: Enabling plugin MyPlugin vv5cd2e67
May 16, 2014 12:26:35 PM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Enabling MyPlugin vv5cd2e67
May 16, 2014 12:26:35 PM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Hello, plugin!
+ ../doppio/doppio-dev -jar build/distributions/Junket-0.0.1-shadow.jar
Hello
May 16, 2014 7:26:39 PM deathcap.junket.Server <init>
INFO: Starting up...
May 16, 2014 7:26:58 PM deathcap.junket.Server <init>
INFO: Loaded 1 plugins
May 16, 2014 7:26:58 PM deathcap.junket.Server <init>
INFO: Enabling plugin MyPlugin vv5cd2e67
May 16, 2014 7:26:58 PM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Enabling MyPlugin vv5cd2e67
May 16, 2014 7:26:58 PM org.bukkit.plugin.PluginLogger log
INFO: [MyPlugin] Hello, plugin!
using 53fb0c7d3cfa48b5f8913cd585332417f90b0e59 on doppio natives_refactor https://github.com/plasma-umass/doppio/commit/1625c920392a0bf80817a62302e860c766091931