Random NullPointerException make the programm crash

Hello, everything in my program is working quite well execpt one thing : Sometime, for no visible reason the program crash and tell me there is a NullPointerExecption in the LWJGL Renderer Thread,5,main]. It usely happen after i click way to much on the screen to make the caracter move. I did try to put some try catch, some throws, but the execption never point any of my code, it only point at Spatial and the render.

[java]
GRAVE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at com.jme3.scene.Spatial.runControlRender(Spatial.java:590)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:655)
at com.jme3.renderer.RenderManager.renderSubScene(RenderManager.java:665)
at com.jme3.renderer.RenderManager.renderScene(RenderManager.java:640)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:974)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1029)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:252)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:185)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Unknown Source)
[/java]

All i want to do is to cancel what ever action cause this mess and then continue. But i donā€™t realy see how i could place a global throws/catch because even after putting one on my app init, it do not work.

Somehow you have added a null control to your spatial.

ā€¦or, you are adding/removing controls to it from a separate thread which is super-duper-bad-donā€™t-ever-do-that.

Well i do have a thing looking like this :

[java]
public void moveTo(Vector3f objectif,float speed)
{
try{
forme.removeControl(move) ;
// move = null ;
move = new ThreadMove(objectif) ;
}
catch(NullPointerException e)
{
System.out.println(ā€œJefessaisplanterā€) ;
}
}
[/java]

and yes the Thread move is a extends of AbstractControl and this whole code come from a call make in the packet section that run on its own thread.

But am not realy sure how i can proced whiout it. I need to change that controle every click i do or someone in the same sever area do. My packet thread is in ScheduledThreadPoolExecutor ( i was getting thread error befaure ) so now it should be okay? Maybie? no? okayā€¦

But seriusly i donā€™t see how i could do it.

You must modify the scene graph ONLY on the render thread. This includes moving the spatial, adding or removing controls, etcā€¦ You must only do it on the render thread. Not a separate thread.

If you need to modify the scene graph from a separate thread then you must have some shared data structure to transfer the info or simply use the Runnable/Callable queue already embedded in JME application. There are tutorials on this.

But if all you are doing is trying to get a ā€˜tickā€™ then you could have trivially coded that as part of an app state and calculate the proper tick on the render thread.

I donā€™t know where a server comes into it because I would personally never use spatials on the server but maybe thatā€™s just me. Itā€™s too much mixing the view with the ā€˜modelā€™.

1 Like

So after i read what you said i decide to put every modification in the render and it seem to be working. As i already mention my thread are in a ScheduledThreadPoolExecutor, i had already read the tutorial on that so the problem did not come from that.

So instead of making any modification (like the removeControle) outisde of the render I decide to go for a boolean and just change it so the render would remove it self

[java]
@Override
protected void controlUpdate(float fps)
{

		try{
		
		forme.lookAt(forme.getWorldTranslation(), objectif) ;
		
		link.moveMe(new Vector3f(targetX*fps*speed,0f,targetZ*fps*speed)) ;
		i+= see*fps ;
		if(i > timmer)
		{
			forme.removeControl(this) ;
			channel.setAnim("stand", 0.50f);
		    channel.setLoopMode(LoopMode.DontLoop);
		    channel.setSpeed(1f);
	       
		}
		if(cutIn)
		{
			forme.removeControl(this) ;
			
	    }
		}
		catch(NullPointerException e)
		{
			System.out.println("Ca viens de la boucle") ;
		}
	}	

[/java]

And no worry, my spatial are outside of the server but what the server do is when you move, it take the information in consideration and send it to everyone, so they can look in theire own Hashtable the name and the information so the spatial in that list would move accordinly. It work very well so far, and whit this little modification it work wihout (to much) bugs.

And as alsways, thanks you very much.

ā€œcatch(NullPointerException e)ā€

ā€¦donā€™t ever ever catch NullPointerException. Itā€™s always a bug.

Iā€™m glad you got things working.

Usually in a client server app, the server sends the move stuff then the client will queue it up for the render code to deal withā€¦ either by using a thread safe data structure like ConcurrentLinkedQueue or by app.enqueue(someObjectThatImplementsCallable) that actually does the moving.