An error from the source code

Hello I’ve just ran into an error which doesn’t help at all. If anyone could give me tip about this kind of exception i would be great-full!

Jun 30, 2016 2:32:19 AM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.IllegalArgumentException: This NativeObject is not registered in this NativeObjectManager
	at com.jme3.util.NativeObjectManager.deleteNativeObject(NativeObjectManager.java:136)
	at com.jme3.util.NativeObjectManager.deleteUnused(NativeObjectManager.java:188)
	at com.jme3.renderer.opengl.GLRenderer.postFrame(GLRenderer.java:863)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:190)
	at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:192)
	at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:233)
	at java.lang.Thread.run(Thread.java:745)

Can you please provide the minimum code, which throws this exception? There is also a thread with the same issue, which might help.

This is my question what kind of code could cause this error to triger. It would take to many time to test since it seem to be crashing randomly at a given time.
I m working on a project with about 100k code ligne and the problème got triggered by the engine it self so it s quite hard to trace back when it occure randomly after a couple of minute of gameplay.
The last thing I’ve added was an infinite map generator/loader and the game would use 2.2go RAM at the same time. I was testing using flying mode all arroubd the map to see how fast the map can be generated and draw.
Anyway if anyone as any tip on the subject of what could be triggering this i would be glad to work on this bug since it could happen again during people game time and i will probably get anoyed until i fix this! xD

I guess it is hard to help with this issue, if there are little details. @Momoko_Fan was a developer of that method, which throws the exception. Maybe he can give some insight.

If I had such rare issue, I would try to track it myself. First by setting a breakpoint in the throw line:

if (ref2 == null) {
                    throw new IllegalArgumentException("This NativeObject is not " + 
                                                       "registered in this NativeObjectManager");
}

because exception is not very informative, and we don’t know what class overrides NativeObject, when this exception occurs.

I understand but there is no way knowing what s actually bugging since it s so rare.

There is 2 possibilities

First: I did something I should no be doing somewhere and it only happen when the ram/cpu load is heavy.

Second: There is actually a bug in the engine there and it occur when the load is high.

The only way to find out is to have feedback about what could make this happening. What kind of function call could happen. And since the error isn’t giving any information I could only end up wasting impossible amount of time. Maybe it only happening on my pc.

Btw, I m working with the version 3.1 alpha

I bet on multithreading issue, you do something on another thread that is so fast that is always done in time but when you are under high loads.

I though about it too, but all of my multi thread as to be processed once finish by the update loop. Anyway until I get more information about the exception I wont play to much around it.

The game look like this and it load chunk (like other infinite world)

There is chunk that as PostProcessWater, and i think it could be the reason of the bug since it started to happen when i added more speed to the FlyByCamera and the lake. But it could be again the speed at witch the chunk load unload and tree and other stuff…

Since you mentioned that you’re using multiple threads and loading chunks there, you might be manipulating objects that the renderer is using.

This issue actually should be fairly straightforward to debug, because you can track all modifications that occur to refMap in that code so you can see who is removing your object’s getUniqueId from refMap.

2 Likes

Yea i don’t think I;m attaching or detaching any node inside my multithread, but I found something worst 5 sec ago… before the NativeObject Crash my whole rootNode wasn’t responding. I could see the lake moving in the screen but the whole Terrain/Trees/Rocks where stand still and i think anything attached to the rootNode :frowning: I have no clue what s causing the issue but I was able to crash the game by swapping the camera view to my Building mode and it crashed. 1 thing is certain the GuiNode was perfectly working, I could open and close my inventory when ever i want.

So my first though would be the rootNode or a node right after lose it reference and then i try to attach something to it but since it lost it reference it would point into the void causing a crash since the reference is null.
I wonder, could it be possible the garbage collector destroy a reference by mistake?
ps: My game use around 2-3go of ram.

Jul 04, 2016 1:52:43 AM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.IllegalArgumentException: This NativeObject is not registered in this NativeObjectManager
    at com.jme3.util.NativeObjectManager.deleteNativeObject(NativeObjectManager.java:136)
    at com.jme3.util.NativeObjectManager.deleteUnused(NativeObjectManager.java:178)
    at com.jme3.renderer.opengl.GLRenderer.postFrame(GLRenderer.java:863)
    at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:190)
    at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:192)
    at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:233)
    at java.lang.Thread.run(Thread.java:745)

Null reference means NPE.

Nope.

Most likely you do something from another thread without realizing it. Threading should follow extremely (EXTREMELY) strict protocols. Do not read from, write to, or do ANYTHING with a Spatial or any other scene related object from another thread if that object is in any way attached to the main thread.

This is hard for us to debug since we don’t know how your threading works.

I’m quite aware of this, since normally it would crash saying “The Scene was modified during the wrong time” (something like that)
Edit: since I can’t write at all…
Normally I wouldn’t do this kind of mistake, but if you guys say it’s mostly a problem from multithread then I will look closely even if it s quite unusual since I always do something like this for multithread.
The water was move to see if it would stop the problem. Normally it would be a 2 part process

/**
 *
 * @author Julien Green
 */
public class GenerateMapCallable implements Callable, Task {

    private TerrainClient t;
    private int seed, x, y, size;
    private TerrainTexture terrainTexture;
    private MapLW map;
    private Forester forester;
    private UpdateRequestMap updateRequestMap;
    private AssetManager assetManager;
    private WaterFilter filter;

    public GenerateMapCallable(TerrainClient t, TerrainTexture terrainTexture, Forester forester, UpdateRequestMap updateRequestMap, AssetManager assetManager) {
        this.t = t;
        this.seed = t.getSeed();
        this.x = t.getX();
        this.y = t.getY();
        this.size = t.getSize();
        this.terrainTexture = terrainTexture;
        this.forester = forester;
        this.updateRequestMap = updateRequestMap;
        this.assetManager = assetManager;
    }

    @Override
    public Object call() throws Exception {
        MapGenerator mapGenerator = new MapGenerator();
        map = mapGenerator.generate(size, seed, t, terrainTexture);

        return null;
    }
    //Once the task is over, attach everything here
    @Override
    public void task(Main app) {
        System.out.println("Done Generating map: " + x + "," + y + " Size: " + t.getSize());
        //Attach the map here and it physical state
        app.getRootNode().attachChild(map.getTerrainQuad());
        app.getServiceContainer().getBulletAppState().getPhysicsSpace().addAll(map.getTerrainQuad());
        //add water later....
        if (t.getLakeObject().getExist()) {
            LakeGenerator generator = new LakeGenerator();
            filter = generator.postProcessWater(assetManager, t.getLakeObject(), x, y, size);
            map.setWaterFilter(filter);
            app.getServiceContainer().getEnv().addWaterFilter(filter);
        }
        
        PlantTileGenerator tiles = new PlantTileGenerator(
                app.getAssetManager(), map, app.getServiceContainer().getLoadedAsset(), t.getEnvMessage().getTrees(), size, false, forester);

        SendMapConcurently concurrency = new SendMapConcurently(tiles, updateRequestMap);
        updateRequestMap.addClassUpdate(concurrency);

        t.addMap(map);
    }

That will only happen under an extremely narrow set of bad threading circumstances (and can even happen when no threading problems are there at all if you do funny scene update stuff). The lack of this message doesn’t mean your threading is fine. For example, it won’t detect if you are modifying mesh buffers after giving them to the scene or any other related mesh stuff. It won’t detect if you are modifying materials, etc… It ONLY detects that you’ve changed something about a Spatial after updateGeometricState() was run for that frame. That’s it. Maybe 5% of the possible threading bad things one can do.

We’d need to know much more about when the various parts of this were called and from with thread. I also don’t know anything about Forester and whether it keeps stuff around internally or anything.

In general, generating terrain from another thread should follow these steps:
-submit the job to some background thread. Job includes absolutely no existing scene spatials, buffers, etc.
-background thread generates new content 100% without messing with any existing attached scene data. To include not batching things sourced from geometry that is part of the scene already.
-background thread somehow submits itself of its content to be included in the regular scene… and then never does anything with that content ever ever again. In case the job might be reused or something, I’d even go so far as to null out any book-keeping fields (unless you are using the job object itself to add things to the scene then clear them once the objects have been added).
-render thread pulls new content off and adds it to the scene.

At this point, it’s important that the job object never touches it again… either through cache or anything else. It’s forbidden now.

My Pager library that takes care of a lot of this has a slightly extended workflow for freeing the objects again. It also means that I have to be that much more careful with the ‘jobs’ as I keep them around longer and they keep references to their stuff longer. But the workflow is still very specific.

Everything here is exactly checked and the thread is a 1 time use, it get deleted right after
public void task is done to prevent any access from the thread. It s the first time I get this error in the whole game development and it start to scare me.

It would be quite difficult to post the terrain code but the only thing i access is the AssetManager and 1 Material (the terrain material is shared between all the terrain to make thing faster) ← would it be the problem?

Anyway here’a the TerrainQuad generator.

/**
 *
 * @author Julien Green
 */
public class CreatLoadedTerrain {

    private Material mat;

    /**
     *
     * @param android
     * @param hmr
     * @param myTexture
     * @param size
     * @param mapX
     * @param mapY
     * @param colorMap1
     * @param colorMap2
     * @return
     */
    public TerrainQuad LoadedTerrainMaker_Basic(
            boolean android,
            HeightMap hmr,
            TerrainTexture myTexture,
            int size,
            int mapX, int mapY,
            int[][] colorMap1, int[][] colorMap2) {

        TerrainQuad terrain;
        
        
        
        //Set the heightmap Back

        ByteBuffer buff = ByteBuffer.allocateDirect(size * size * 4);
        ByteBuffer buff2 = ByteBuffer.allocateDirect(size * size * 4);
//        System.out.println(size);
        
        for (int x = 0; x < size; x++) {
            for (int y = 0; y < size; y++) {
                buff.asIntBuffer().put(y * size + x, colorMap1[x][size-1-y]);
                buff2.asIntBuffer().put(y * size + x, colorMap2[x][size-1-y]);
                
            }
        }
        
        buff.flip();
        buff2.flip();
        Image img1 = new Image(Image.Format.RGBA8, size, size, buff);
        Image img2 = new Image(Image.Format.RGBA8, size, size, buff2);
        
        Texture2D tex1 = new Texture2D();
        Texture2D tex2 = new Texture2D();
        
        tex1.setImage(img1);
        tex2.setImage(img2);
        
        mat = myTexture.getMat2().clone();

        mat.setTexture("AlphaMap", tex1);
        mat.setTexture("AlphaMap_1", tex2);
        
        int patchSize = size*8;
        terrain = new TerrainQuad("my terrain", patchSize, size + 1, hmr.getHeightMap());

//          mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
//          mat.getAdditionalRenderState().setWireframe(true);
//          mat.setColor("Color", ColorRGBA.Blue);
        terrain.setMaterial(mat);
        terrain.setLocalScale(16f, 2f, 16f);
        terrain.setLocalTranslation(((16 * size) * mapX), 0, ((16 * size) * mapY));

        terrain.setShadowMode(RenderQueue.ShadowMode.Receive);

        //Physic Construction
        CollisionShape terrainShape = CollisionShapeFactory.createMeshShape((Node) terrain);
        RigidBodyControl landscape = new RigidBodyControl(terrainShape, 0);
        terrain.addControl(landscape);
        
        return terrain;
    }

    /**
     *
     * @return
     */
    public Material getMaterial() {
        return mat;
    }

    private Texture2D generateTextureMap(BufferedImage bufferMap) {
        AWTLoader loader = new AWTLoader();
        Image img;
        img = loader.load(bufferMap, true);
        Texture2D tex1 = new Texture2D();
        tex1.setImage(img);
        img.dispose();
        return tex1;
    }
}