A fatal error has been detected by the Java Runtime Environment with LibGDX

Alight, so here is the issue.

I dispose of all my stuff. Just in case it doesn’t call dispose(), I call dispose() in the hide() method for com.badlogic.gdx.Screen. I also use a boolean to make sure even if dispose() is called twice, it only disposes of all images, sprites, ect once.

I can’t be posting all of my code on here, it is way too much. What I have notice though is it always happens when I hit “Play” on the screen. So here is my MainMenu class.


import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.viewport.ScreenViewport;

public class MainMenu implements Screen {
	
	private boolean isDisposed = false;

	private TextureAtlas	atlas;
	private TextButton		buttonPlay;
	private BitmapFont		font;
	private Skin			skin;
	private Stage			stage;

	private Table			table;

	public void dispose() {
		if(!isDisposed) {
			atlas.dispose();
			font.dispose();
			stage.dispose();
			isDisposed = true;
		}
	}

	public void hide() {
		dispose();
	}

	public void pause() {
		// TODO Auto-generated method stub

	}

	public void render(final float delta) {
		Gdx.gl.glClearColor(0, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

		stage.act(delta);
		stage.draw();
	}

	public void resize(final int width, final int height) {
		stage.getViewport().update(width, height);
		table.invalidateHierarchy();
		table.setSize(width, height);
	}

	public void resume() {
		// TODO Auto-generated method stub

	}

	public void show() {
		final FreeTypeFontGenerator generator = new FreeTypeFontGenerator(
				Gdx.files.internal("fonts/Track.ttf"));
		font = generator.generateFont(80);
		generator.dispose();

		stage = new Stage(new ScreenViewport());

		Gdx.input.setInputProcessor(stage);

		atlas = new TextureAtlas(Gdx.files.internal("img/game.pack"));
		skin = new Skin(atlas);

		table = new Table(skin);
		table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

		final TextButtonStyle textButtonStyle = new TextButtonStyle();
		textButtonStyle.up = skin.getDrawable("button_up");
		textButtonStyle.down = skin.getDrawable("button_down");
		textButtonStyle.pressedOffsetX = 1;
		textButtonStyle.pressedOffsetY = -1;
		textButtonStyle.font = font;
		textButtonStyle.fontColor = Color.WHITE;

		buttonPlay = new TextButton("Play", textButtonStyle);
		buttonPlay.addListener(new ClickListener() {
			@Override
			public void clicked(final InputEvent event, final float x,
					final float y) {
				((Game) Gdx.app.getApplicationListener()).setScreen(new World(1));
			}
		});
		buttonPlay.pad(20);

		table.add(buttonPlay);
		stage.addActor(table);
	}

}

Also, Here is the error I get in the console.

It also logs two files.

hs_err_pid3320.log - http://pastebin.com/ZG8Ek98R

replay_pid3320.log - http://pastebin.com/bn0GdGnf

I have tried some things, like putting dispose() in the hide() method. However, I am not exactly sure what to do with this type of crash/error as I have never seen anything like it before. Thanks for any help / guidance on the issue.

Without completely reading:
The error looks familar. Are you somewhere spamming the RAM?

I’ve seen this error before, I’m guessing you’re disposing something that you are still using later?

I do not believe I am spamming the RAM. I am only loading a bitmap font and atlas once. When I fire a bullet for example, that object is assigned one sprite. I do not delete that sprite’s texture because it has to be re used for other objects. If you did, all images would go black. (Image atlas would need to be re-loaded)

I do re-load the same atlas for each screen, but I dispose of it before I re-load it. This shouldn’t matter.

Having looked over LibGDX practices as far as keeping memory from being flooded and do believe I am following them correctly.

Also, using VisualVM I did not see any apparent memory leaks. All garbage seemed to be taken care of and RAM used stayed below 10MB. However, when the application does fail (10 to 20% of the time) then I can’t profile the app during those instances. So I am blind when it counts most.

Can you please try with JDK Version 7?

So you mean revert from JDK 8 to JDK7? I will try to install it as an alternative now.

Remove all the dispose calls, see if it works. Add them back one at a time until it crashes.

That was actually very helpful to do.

The code that would trigger the crash was not in the MainMenu, but rather the Splash screen.

Whenever I would dispose of the SpriteBatch that I created, it would crash about 10 to 20% of the time.

Should I not dispose of this?

@imagnity I tried, but still crashed.

General advice: Instead of playing hit and miss to find where the error lies you should always use line-by-line debugging to find the source of the error.

This kind of error is familiar to me too, I think it happened to me when I uploaded a buffer to OpenGL without flipping it first, so basically when you’re trying to access memory that doesn’t belong to your application (although I’m not 100% sure in this).

As of whether or not you should dispose your SpriteBatch: Yes, absolutely if you’re not going to use it later on it shouldn’t cause any errors.

Line by line debugging is my new favourite thing. Helped me solve the issue. The problem wasn’t anything being disposed. It was where I had my tweenManager.update(). It was before batch.end() and a batch.draw(sprite). That is a huge issue. I just put it afterwards. Too bad this causes my tween to not work properly, at least I can figure it out from here. Thanks for all the help guys!

I would have never seen it without line by line debugging… new tool for the win! :slight_smile:

EDIT:

Added tweenManager.update(Float.MIN_VALUE); during com.badlogic.gdx.Screen.show() method, or whenever you create it, and it works like a charm now!