sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Can't open scene due to broken control

Open neph1 opened this issue 4 months ago • 4 comments

From Renzote on discord: "Good afternoon, can anyone help me, please? I created my j3o model in the SDK. Everything was fine, I had done a lot with it, but just when I added my custom controller and saved the j3o, this error appeared when I reopened the file. What is causing this and what can I do?"

Image Image

Related? https://github.com/jMonkeyEngine/sdk/issues/640

neph1 avatar Aug 24 '25 05:08 neph1

The error is thrown from Spatial.getControl, presumably since the SDK has added a "null" control to the list.

neph1 avatar Aug 24 '25 05:08 neph1

I can reproduce this by adding a simple custom control to a scene, saving and loading.

java.lang.ClassNotFoundException: com.mygame.TestControl starting from ModuleCL@2b76fa71[com.jme3.gde.core.baselibs] with possible defining loaders null and declared parents [ModuleCL@152a7b06[com.jme3.gde.core.libraries]] at org.netbeans.ProxyClassLoader.doFindClass(ProxyClassLoader.java:226) at org.netbeans.ProxyClassLoader.loadClass(ProxyClassLoader.java:140) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:421) at java.base/java.lang.Class.forName(Class.java:412) at com.jme3.export.SavableClassUtil.findNoArgConstructor(SavableClassUtil.java:243) at com.jme3.export.SavableClassUtil.fromName(SavableClassUtil.java:187) at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:332) at com.jme3.export.binary.BinaryInputCapsule.resolveIDs(BinaryInputCapsule.java:510) at com.jme3.export.binary.BinaryInputCapsule.readSavableArray(BinaryInputCapsule.java:498) at com.jme3.export.binary.BinaryInputCapsule.readSavableArrayList(BinaryInputCapsule.java:616) at com.jme3.scene.Spatial.read(Spatial.java:1663) at com.jme3.scene.Node.read(Node.java:776) at com.jme3.export.binary.BinaryImporter.readObject(BinaryImporter.java:340) at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:245) at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:128) at com.jme3.export.binary.BinaryImporter.load(BinaryImporter.java:112) at com.jme3.export.binary.BinaryLoader.load(BinaryLoader.java:36) at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:274) at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:390) at com.jme3.asset.DesktopAssetManager.loadModel(DesktopAssetManager.java:441) at com.jme3.gde.core.assets.SpatialAssetDataObject.loadAsset(SpatialAssetDataObject.java:93) at com.jme3.gde.scenecomposer.OpenSceneComposer.lambda$actionPerformed$1(OpenSceneComposer.java:35) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: java.lang.ClassNotFoundException: com.mygame.TestControl at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) at org.netbeans.ProxyClassLoader.doFindClass(ProxyClassLoader.java:224) ... 24 more

neph1 avatar Aug 24 '25 06:08 neph1

Current theory is this.

Some time ago, a SavableClassUtil.fromName that took classLoaders as a parameter was deprecated:

    /**
     * @deprecated use {@link #fromName(java.lang.String)} instead 
     */
    @Deprecated
    public static Savable fromName(String className, List<ClassLoader> loaders) throws InstantiationException,
            InvocationTargetException, NoSuchMethodException,
            IllegalAccessException, ClassNotFoundException, IOException {
...
}

This method tried to use supplied classLoaders to load a class before falling back to the default one. It's my theory that the switch to the new fromName method caused this problem.

ProjectAssetManager uses addClassLoader(loader); (now deprecated, too)

I've tried using Thread.currentThread().setContextClassLoader(loader); but to no avail, it's using the com.jme3.gde.core (or somethings) classloader instead of the projects, which makes it unable to load controls on the project's classpath.

(I've verified that the control is loadable via ProjectAssetManager's loader.)

neph1 avatar Aug 25 '25 19:08 neph1

@riccardobl could I have your input on this? is this change the likely culprit? Would it be feasible with a fallback option for the SDK?

neph1 avatar Aug 26 '25 14:08 neph1