I Get a java.lang.NullPointerException I cant fix

I sometimes get this error when i press the play button on my game and it crashes
Exception in thread “Thread-2” java.lang.NullPointerException
at com.GamerC4.main.Handler.render(Handler.java:25)
at com.GamerC4.main.Game.render(Game.java:149)
at com.GamerC4.main.Game.run(Game.java:96)
at java.lang.Thread.run(Unknown Source)

Here is my code

package com.GamerC4.main;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.awt.Color;
import java.util.Random;
public class Game extends Canvas implements Runnable
{
private static final long serialVersionUID = 1550691097823471818L;

public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9; 

private Thread thread;
private boolean running = false;

private Random r;
private Handler handler;
private HUD hud;
private Spawn spawner;
private Menu menu;

public enum STATE
{
	Menu,
	Game,
	Help,
	End;
};

public static STATE gameState = STATE.Menu;

public Game()
{
	handler = new Handler();
	hud = new HUD();
	menu = new Menu(this, handler, hud);
	this.addKeyListener(new KeyInput(handler)); 
	this.addMouseListener(menu);
	
	new Window(WIDTH, HEIGHT, "Trails", this);

	spawner = new Spawn(handler, hud);
	menu = new Menu(this, handler, hud);
	r = new Random();
	
	if(gameState== STATE.Game)
	{
	handler.addObject(new Player(WIDTH/2-32, HEIGHT/2-32, ID.Player, handler));
	handler.addObject(new BasicEnemy(r.nextInt(Game.WIDTH), r.nextInt(Game.HEIGHT), ID.BasicEnemy, handler));
	}else
	{
		for(int i = 0; i < 20; i++)
		{
			handler.addObject(new menuParticleEffect(r.nextInt(WIDTH), r.nextInt(HEIGHT), ID.MenuParticle, handler));
		}
	}
}
public synchronized void start()
{
	thread = new Thread(this);
	thread.start();
	running = true;
}

public synchronized void stop()
{
	try
	{
		thread.join();running = false;
	}catch(Exception e)
	{
		e.printStackTrace();
	}
}
public void run()
{
	this.requestFocus();
	long lastTime = System.nanoTime();
	double amountOfTicks = 60.0;
	double ns = 1000000000 / amountOfTicks;
	double delta = 0;
	long timer = System.currentTimeMillis();
	int frames = 0;
	while(running)
	{
		long now = System.nanoTime();
		delta += (now - lastTime) / ns;
		lastTime = now;
		while( delta >= 1)
		{
			tick();
			delta--;
		}
		if(running)
			render();
		frames++;
		
		if(System.currentTimeMillis() - timer > 1000)
		{
			timer += 1000;
			//System.out.println("FPS: " + frames);
			frames = 0;
		}
	}
	stop();
}

private void tick ()
{
	handler.tick();
	if(gameState == STATE.Game)
	{
		hud.tick();
		spawner.tick();
		
		if(HUD.HEALTH <= 0)
		{
			HUD.HEALTH = 100;
			gameState = STATE.End;
			handler.clearEnemys();
			for(int i = 0; i < 20; i++)
			{
				handler.addObject(new menuParticleEffect(r.nextInt(WIDTH), r.nextInt(HEIGHT), ID.MenuParticle, handler));
			}
		}
		
	}else if(gameState == STATE.Menu || gameState == STATE.End)
	{
		menu.tick();
	}

}

private void render()
{
	BufferStrategy bs = this.getBufferStrategy();
	if(bs == null)
	{
		this.createBufferStrategy(3);
		return;
	}
	
	Graphics g = bs.getDrawGraphics();
	
	g.setColor(Color.black);
	g.fillRect(0, 0, WIDTH, HEIGHT);
	
	handler.render(g);
	
	if(gameState == STATE.Game)
	{
	hud.render(g);
	}else if(gameState == STATE.Menu || gameState == STATE.Help || gameState == STATE.End){
			menu.render(g);
	}
	
	g.dispose();
	bs.show();
}

public static float clamp(float var, float min, float max)
{
	if(var >= max)
	{
		return var = max;
	}
	else if (var <= min)
	{
		return var = min;
	}
	else
	{
		return var;
	}
}

public static void main(String[] args)
{
	new Game();
}

}


package com.GamerC4.main;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.LinkedList;
import java.awt.*;
public class Handler
{
//LinkedList object = new LinkedList();
public java.util.List object = new ArrayList();

public void tick()
{
	for( int i = 0; i < object.size(); i++ )
	{
		GameObject tempObject = object.get(i);
		tempObject.tick();
	}
}

public void render(Graphics g)
{
	for( int i = 0; i < object.size(); i++ )
	{
		GameObject TempObject = object.get(i);
		TempObject.render(g);
	}
}

public void clearEnemys()
{
	for( int i = 0; i < object.size(); i++ )
	{
		GameObject TempObject = object.get(i);
		
		if(TempObject.getId() != ID.Player)
		{
			object.clear();
			if(Game.gameState != Game.STATE.End)
			{
			addObject(new Player((int)TempObject.getX(), (int)TempObject.getY(),  ID.Player, this));
			}
		}
	}
}

public void addObject(GameObject object)
{
	this.object.add(object);
}

public void removeObject(GameObject object)
{
	this.object.remove(object);
}

}

TempObject.render(g); <- line 25 I’m guessing?

TempObject is null, as in your list contains at least one null value.
It’s quite possibly a race condition. I would eliminate as much usage of threading as possible.

Also it would be a bit nicer to just do :


object.get(i).render(g);

Thank you, but I still have a new error Exception in thread
“Thread-2” java.lang.NullPointerException
at java.util.LinkedList.node(Unknown Source)
at java.util.LinkedList.get(Unknown Source)
at com.GamerC4.main.Handler.render(Handler.java:25)
at com.GamerC4.main.Game.render(Game.java:149)
at com.GamerC4.main.Game.run(Game.java:96)
at java.lang.Thread.run(Unknown Source)

after changing line 25 to object.get(i).render(g);

How are you getting a LinkedList error? The code you posted had the LinkedList object array commented out and the ArrayList being used.

Probably changed the code back to an LL to try and fix it.
If internal LL methods are throwing an NPE, then it’s almost certainly a race condition. Changing that line to object.get(i).render(g); has nothing to do with it.

The easiest way to fix it is to only access the objects list from one thread. Barring that, you can use a lock when accessing the list.

sorry my bad

I’m getting
Exception in thread “Thread-2” java.lang.IndexOutOfBoundsException: Index: 777, Size: 2
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at com.GamerC4.main.Handler.render(Handler.java:25)
at com.GamerC4.main.Game.render(Game.java:149)
at com.GamerC4.main.Game.run(Game.java:96)
at java.lang.Thread.run(Unknown Source)

If you’ve made changes since your original post, could you post your current code? (Using code blocks or pastebin will preserve formatting and provide syntax highlighting, which will make the code easier to read.)

[quote]Exception in thread “Thread-2” java.lang.IndexOutOfBoundsException: Index: 777, Size: 2
[/quote]
Last time I’ll say it: race condition. Looks like one thread is clearing the list, while the other is still reading from it. Sometimes you get a NPE, sometimes an out of bounds exception, and sometimes nothing bad happens, which is the worst.

If you want any help with it, you’ll have to post any code that accesses the list, not just where the list is defined.

package com.GamerC4.main;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;

import com.GamerC4.main.Game.STATE;

public class Menu extends MouseAdapter
{
   
   private Game game;
   private Handler handler;
   private Random r = new Random();
   private HUD hud;
   
   public Menu(Game game, Handler handler, HUD hud)
   {
      this.game = game;
      this.handler = handler;
      this.hud = hud;
   }
   
   public void mousePressed(MouseEvent e)
   {
      int mx =e.getX();
      int my = e.getY();
      if(game.gameState == STATE.Menu)
      {
         
      
         if(mouseOver(mx, my, 210, 150, 200, 64))
         {
            game.gameState = STATE.Game;
            hud.setScore(0);
            hud.setLevel(1);
            handler.addObject(new Player(Game.WIDTH/2-32, Game.HEIGHT/2-32, ID.Player, handler));
            handler.clearEnemys();
            handler.addObject(new BasicEnemy(r.nextInt(Game.WIDTH), r.nextInt(Game.HEIGHT), ID.BasicEnemy, handler));
         }
      
         if(mouseOver(mx, my, 220, 350, 200, 64))
         {
            System.exit(1);
         }
         if(mouseOver(mx, my, 210, 250, 200, 64))
         {
            game.gameState = STATE.Help;
         }
      }
      
   
      if(game.gameState == STATE.End)
      {
         if(mouseOver(mx, my, 210, 350, 200, 64))
         {
            game.gameState = STATE.Menu;
            return;
         }
      }
      if(game.gameState == STATE.Help)
      {
         if(mouseOver(mx, my, 210, 350, 200, 64))
         {
            game.gameState = STATE.Menu;
            return;
         }
      }
   }
   
   public void mouseReleased(MouseEvent e)
   {
      
   }
   
   private boolean mouseOver(int mx, int my, int x, int y, int width, int height)
   {
      if(mx > x && mx < x + width)
      {
         if(my > y && my < y + height)
         {
            return true;
         }else return false;
      }else return false;
   }
   
   public void tick()
   {
      
   }
   public void render(Graphics g)
   { 
      if(game.gameState == STATE.Menu)
      {
      Font fnt = new Font("arial", 1, 50);
      Font fnt2 = new Font("arial", 1, 30);
      
      g.setFont(fnt);
      g.setColor(Color.white);
      g.drawString("Trails", 240, 70);
      
      g.setFont(fnt2);
      g.setColor(Color.white);
      g.drawRect(210, 150, 200, 64);
      g.drawString("Play", 270, 190);
      
      g.setFont(fnt2);
      g.setColor(Color.white);
      g.drawRect(210, 250, 200, 64);
      g.drawString("Help", 270, 290);
      
      g.setFont(fnt2);
      g.setColor(Color.white);
      g.drawRect(210, 350, 200, 64);
      g.drawString("Quit", 270, 390);
      }else if(game.gameState == STATE.Help)
      {
         Font fnt = new Font("arial", 1, 50);
         Font fnt2 = new Font("arial", 1, 30);
         Font fnt3 = new Font("arial", 1, 20);
         
         g.setFont(fnt);
         g.setColor(Color.white);
         g.drawString("Help",240, 70);
         
         g.setFont(fnt3);
         g.drawString("Use the arrow keys to move and dodge enemies.", 50, 100);
         
         g.setFont(fnt2);
         g.setColor(Color.white);
         g.drawRect(210, 350, 200, 64);
         g.drawString("Back", 270, 390);
      }
      else if(game.gameState == STATE.End)
      {
         Font fnt = new Font("arial", 1, 50);
         Font fnt2 = new Font("arial", 1, 30);
         Font fnt3 = new Font("arial", 1, 20);
         
         g.setFont(fnt);
         g.setColor(Color.RED);
         g.drawString("Game Over",180, 70);
         
         g.setFont(fnt3);
         g.drawString("You left this game with a score of " + hud.getScore(), 175, 100);
         
         g.setFont(fnt2);
         g.setColor(Color.GREEN);
         g.drawRect(210, 350, 200, 64);
         g.drawString("Restart", 245, 390);
      }
   }
}

package com.GamerC4.main;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.awt.Color;
import java.util.Random;
public class Game extends Canvas implements Runnable
{
   private static final long serialVersionUID = 1550691097823471818L;
   
   public static final int WIDTH = 640, HEIGHT = WIDTH / 12 * 9; 
   
   private Thread thread;
   private boolean running = false;
   
   private Random r;
   private Handler handler;
   private HUD hud;
   private Spawn spawner;
   private Menu menu;
   
   public enum STATE
   {
      Menu,
      Game,
      Help,
      End;
   };
   
   public static STATE gameState = STATE.Menu;
   
   public Game()
   {
      handler = new Handler();
      hud = new HUD();
      menu = new Menu(this, handler, hud);
      this.addKeyListener(new KeyInput(handler)); 
      this.addMouseListener(menu);
      
      new Window(WIDTH, HEIGHT, "Trails", this);
   
      spawner = new Spawn(handler, hud);
      menu = new Menu(this, handler, hud);
      r = new Random();
      
      if(gameState== STATE.Game)
      {
      handler.addObject(new Player(WIDTH/2-32, HEIGHT/2-32, ID.Player, handler));
      handler.addObject(new BasicEnemy(r.nextInt(Game.WIDTH), r.nextInt(Game.HEIGHT), ID.BasicEnemy, handler));
      }else
      {
         for(int i = 0; i < 20; i++)
         {
            handler.addObject(new menuParticleEffect(r.nextInt(WIDTH), r.nextInt(HEIGHT), ID.MenuParticle, handler));
         }
      }
   }
   public synchronized void start()
   {
      thread = new Thread(this);
      thread.start();
      running = true;
   }
   
   public synchronized void stop()
   {
      try
      {
         thread.join();running = false;
      }catch(Exception e)
      {
         e.printStackTrace();
      }
   }
   public void run()
   {
      this.requestFocus();
      long lastTime = System.nanoTime();
      double amountOfTicks = 60.0;
      double ns = 1000000000 / amountOfTicks;
      double delta = 0;
      long timer = System.currentTimeMillis();
      int frames = 0;
      while(running)
      {
         long now = System.nanoTime();
         delta += (now - lastTime) / ns;
         lastTime = now;
         while( delta >= 1)
         {
            tick();
            delta--;
         }
         if(running)
            render();
         frames++;
         
         if(System.currentTimeMillis() - timer > 1000)
         {
            timer += 1000;
            //System.out.println("FPS: " + frames);
            frames = 0;
         }
      }
      stop();
   }
   
   private void tick ()
   {
      handler.tick();
      if(gameState == STATE.Game)
      {
         hud.tick();
         spawner.tick();
         
         if(HUD.HEALTH <= 0)
         {
            HUD.HEALTH = 100;
            gameState = STATE.End;
            handler.clearEnemys();
            for(int i = 0; i < 20; i++)
            {
               handler.addObject(new menuParticleEffect(r.nextInt(WIDTH), r.nextInt(HEIGHT), ID.MenuParticle, handler));
            }
         }
         
      }else if(gameState == STATE.Menu || gameState == STATE.End)
      {
         menu.tick();
      }
   
   }
   
   private void render()
   {
      BufferStrategy bs = this.getBufferStrategy();
      if(bs == null)
      {
         this.createBufferStrategy(3);
         return;
      }
      
      Graphics g = bs.getDrawGraphics();
      
      g.setColor(Color.black);
      g.fillRect(0, 0, WIDTH, HEIGHT);
      
      handler.render(g);
      
      if(gameState == STATE.Game)
      {
      hud.render(g);
      }else if(gameState == STATE.Menu || gameState == STATE.Help || gameState == STATE.End){
            menu.render(g);
      }
      
      g.dispose();
      bs.show();
   }
   
   public static float clamp(float var, float min, float max)
   {
      if(var >= max)
      {
         return var = max;
      }
      else if (var <= min)
      {
         return var = min;
      }
      else
      {
         return var;
      }
   }
   
   public static void main(String[] args)
   {
      new Game();
   }
}

I’m sorry burntpizza I dont understand but here is my new code

Please, please, please use Pastebin or syntax highlighting. It’s painful to have to read through code that’s not highlighted, or at least formatted.

@The OP: If you’re not sure how to property format your code, the easiest solution is probably to use the ‘code’ option in the post editor. (Pastebin may be better in general for larger amounts of code, but just including the code directly in a post would probably be fine here.) To format your code in your post, highlight the code and then click the formatting button with the number sign on it. Or, you can just manually add ‘code’ at the beginning of your code and ‘/code’ at the end (both in square brackets).

Also, I gather from previous posts that you’re using multithreading. Is this something that’s required by whatever framework(s) you’re using? If not, can you clarify what the purpose of the multithreading is?

Fixed it I now know how to insert code

This is my first java game and i was using alot of youtube tutorials for this and multi-threading is what the tutorial told me to do

Menu#mousePressed modifies Handler#object and is called from the event dispatch thread whenever the mouse is pressed inside the component.
Meanwhile Handler#render and Handler#clearEnemies and some other places are accessing and modifying the list from your Runnable thread, Thread-2.
You need to keep the list behind a lock or simply not access it on more than 1 thread. I recommend not accessing it from the mousePressed method.

[quote]This is my first java game and i was using alot of youtube tutorials for this and multi-threading is what the tutorial told me to do
[/quote]
Well it wasn’t a good tutorial.

Well it wasn’t a good tutorial.
[/quote]
I’m sorry but I’m a bit new to game programming. May I ask exactly how to do it. Sorry to drag this out so long

Also, thanks for helping me this far

A good idea to keep in mind is to separate the event reporting (and rendering) from the logic of the game. Since events can be thought of a stream of things over time, a queue is good for this:


mousePressed:
    put an event into queue;

tick():
    while (queue isnt empty) process event in queue;
    do rest of game logic;

game loop:
    tick();
    render();
    sleep();

Since two thread are touching this queue, you still need a lock mechanism of some kind, but this isn’t as big a deal as each thread only accesses it in one place. Plus, queues with internal locks are already made for you: BlockingQueue
The fool-proof implementation is LinkedBlockingQueue, as it automatically grows to any size (up to maximum integer).
The methods you would be interested in are offer and poll.