I keep getting the following exception and can’t find the reason:
SCHWERWIEGEND: Uncaught exception thrown in Thread[jME3 Main,5,main]
java.lang.ArrayIndexOutOfBoundsException: 69
at com.jme3.util.SafeArrayList.get(SafeArrayList.java:258)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:683)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:683)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:662)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1019)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1078)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:260)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:152)
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)
This happens randomly at any point while I am running the game, either directly after starting, while loading the scene or when I am just floating around with the camera over my scene. Sometimes I do not get an exception but the game is freezing and the only way to get out is killing the process. I do only use mutlithreading at one point and the exception does also happen when I disable the feature (the minimap btw). So that does not seem to be the reason.
I have absoluetly no idea where this may come from and would be happy on any suggestions…
@pspeed
The node where this happens is a normal node that is holding the buildings (only trees right now). This game is my first serious try with networking, the server is sending messages when a new building should be attached to the node. I had an eye on that, the messages are stored in a list until the next update call and are added then to avoid changing the scene when it shouldn’t be changed but I guess I might have done anything wrong there… I am gonna check it again and tell you if I found something
Haha, thank you for that hint. I should say I never professionally “learned” programming, it’s just a hobby so I probably might do some bullshit… I am going to rewrite the message handling with Callables (I did hardly use before…)
Any suggestions what I should definetely have an eye on?
I love you all I do now work with Callables to handle the messages and they 1) Are much faster and 2) I could remove everything to make it Thread safe and it still works… My code looks so much better now^^
I keep having the same issue, even after reconstructing the whole process of adding buildings…
I found the source of the problems (if I comment it out the don’t occur) but I have no idea what I am doing wrong:
/**
* Adds a building to the scene
* @param bc The BuildingCreator
* @throws java.lang.Exception if the building could not be added
*/
public void addBuilding(final BuildingCreator bc) throws Exception{
if(bc != null && map != null && this.app.getBuildingNode() != null){ //Do not add if the game has not finished loading yet
final Spatial building = bc.createBuilding(app.getAssetManager()); //Load the building (just preparing the spatial)
building.addControl(new HeightControl(app.getClientMap())); //Add a control to adjust the height to the terrain if it is changed
this.app.enqueue(new Callable<Spatial>() {
@Override
public Spatial call() throws Exception {
app.getBuildingNode().attachChild(building); //HERE IS WHERE THE EXCPETION HAPPENS!
return building;
}
});
}
}
The scene is not modified anywhere else.
Please help me, I don’t know what else to do…
Why? (ie: why not wrap the whole addBuilding() body in the enqueue?)
What is the latest exception? Stack traces are important.
What does createBuilding() do?
If that line is truly where the exception is happening (hard to tell without a stack trace) then you still have another thread somewhere modifying the scene graph.
If this code is being called from a separate thread then the following line is bad because it is accessing a global non-thread-safe data member. At best it is suspicious. Don’t know get getBuildingNode() is doing so it’s hard to say.
addBuilding() is called when the client receives the message from the server that a building should be added. The message contains the BuildingCreator that stores the data (type of the building, position, rotation).
What does createBuilding() do?
CreateBuilding() creates a new spatial and adds the model (depending on the type) and sets it’s localRotation and LocalTranslation.
Why? (ie: why not wrap the whole addBuilding() body in the enqueue?)
I did wrap the whole stuff in the enqueue before but had the same problem so I thought it was better to take it out since the rest is not changing the scene graph.
Looks wrong, though.
I do also not like that line I had the problem that the messages with the buildings came too early sometimes and I got NullPointers because the game did not finish loading. I still get the IndexOutOfBoundsException if I take it out so it can’t be the problem. getBuildingNode() just returns the node buildings are attached to. I wanted to shorten
“((Node)getRootNode().getChild(“buildings”))”
, it does exactly the same.
If that line is truly where the exception is happening (hard to tell without a stack trace) then you still have another thread somewhere modifying the scene graph.
I get no exception if I comment that one line (and only that line) out. Also I did usage searches for every attachChild() and detachChild() usage and none of them can be called here.
Another thing I just realized: It only happens if I add a large amount of buildings the same time. Single buildings are no problem. Do you think that could be the reason or is it just that the chances to have a simultan modification somewhere else are (of course) much higher with more buildings?
Here is the latest exception. I tried catching it since it would not be a problem to have buildings not added because they are requested again later but then I get the exception while rendering you see in my first post. The Indeces are always different what would support my theory why the chance to get the exception is higher with more buildings.
java.lang.IndexOutOfBoundsException: Index: 152, Size: 151
at java.util.ArrayList.rangeCheckForAdd(ArrayList.java:661)
at java.util.ArrayList.add(ArrayList.java:473)
at com.jme3.util.SafeArrayList.add(SafeArrayList.java:269)
at com.jme3.scene.Node.attachChildAt(Node.java:346)
at com.jme3.scene.Node.attachChild(Node.java:321)
at leader.game.ClientGraphicAppState$1.call(ClientGraphicAppState.java:150)
at leader.game.ClientGraphicAppState$1.call(ClientGraphicAppState.java:146)
at com.jme3.app.AppTask.invoke(AppTask.java:142)
at com.jme3.app.Application.runQueuedTasks(Application.java:667)
at com.jme3.app.Application.update(Application.java:681)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:234)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:152)
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)
This will cause an exception if you call it while the main thread is attaching things to the root node. Or it may cause the other thread to throw an exception. It’s not thread safe so don’t call it from another thread.
You error is 100000% caused by accessing the scene graph from multiple threads. So don’t do that. Then repeat.
No you cannot even GET things (like getNodes()) from another thread. Don’t do it. Just don’t. Eliminate all cases where you access the attached scene graph (root node on down) from another thread and then your problem will go away.
I put the whole task back in the enqueue and WOOSH it works!
I don’t know why I got the exception before I took it out but I guess I had something similar elsewhere…
I will have an eye on that now. You never stop learning
Thank you very much for your help, I guess I would have never figured it out alone!