简体   繁体   中英

Box2d Memory Leak

I have determined that box2d is causing a memory leak. After just 20 minutes, it goes from occupying 10% of the application memory, all the way to 50%. The object count at the start of the game is 100,000. That number (even after GC) rises to above 1.5 million. The application is not only slowed on android, but desktop starts to run poorly too. Initially it runs fine, but after 5 minutes it starts to look laggish. I will link the relevant code below. But first, here is some more info :

I needed to dynamically change the fixture size for these bodies. So my solution is to destroy/recreate the fixtures to the appropriate size every frame. There are a total of 8 objects (all the same as the code below) that use box2d. These objects are the only potential leaking point I believe.

The method below is called every frame for the 8 enemy objects I mentioned earlier. I should also say that the value 'true' IS passed into this method each call. As you will see, I am disposing of the fixtures and the shapes, so I'm not sure how a memory leak could occur.

private void createFixtures(boolean remove) {

    if (remove) {
        if (fixture_inner != null) {
            if(body.getFixtureList().contains(fixture_inner, false)) {
                body.destroyFixture(fixture_inner);
            }
        }
        if (fixture_outer != null) {
            if(body.getFixtureList().contains(fixture_outer, false)) {
                body.destroyFixture(fixture_outer);
            }
        }
        if (fixture_gap != null) {
            if(body.getFixtureList().contains(fixture_gap, false)) {
                body.destroyFixture(fixture_gap);
            }
        }
    }

    if (getInnerBounds() != null) {
        FixtureDef fixtureDef_inner = new FixtureDef();
        PolygonShape shape_inner = new PolygonShape();
        shape_inner.set(getInnerBounds().getTransformedVertices());
        fixtureDef_inner.shape = shape_inner;
        fixtureDef_inner.filter.categoryBits = Config.CATEGORYBIT_BLOCKER;
        fixtureDef_inner.filter.maskBits = Config.CATEGORYBIT_PLAYER;
        fixtureDef_inner.isSensor = true;
        fixture_inner = body.createFixture(fixtureDef_inner);
        BlockerFixtureUserData fixtureUserData_inner = new BlockerFixtureUserData(this, gameObjects.indexOf(this, false));
        fixture_inner.setUserData(fixtureUserData_inner);

        shape_inner.dispose();
    }

    if (getOuterBounds() != null) {
        FixtureDef fixtureDef_outer = new FixtureDef();
        PolygonShape shape_outer = new PolygonShape();
        shape_outer.set(getOuterBounds().getTransformedVertices());
        fixtureDef_outer.shape = shape_outer;
        fixtureDef_outer.filter.categoryBits = Config.CATEGORYBIT_BLOCKER;
        fixtureDef_outer.filter.maskBits = Config.CATEGORYBIT_PLAYER;
        fixtureDef_outer.isSensor = true;
        fixture_outer = body.createFixture(fixtureDef_outer);
        BlockerFixtureUserData fixtureUserData_outer = new BlockerFixtureUserData(this, gameObjects.indexOf(this, false));
        fixture_outer.setUserData(fixtureUserData_outer);

        shape_outer.dispose();
    }

    if (getGapBounds() != null) {
        FixtureDef fixtureDef_gap = new FixtureDef();
        PolygonShape shape_gap = new PolygonShape();
        shape_gap.set(getGapBounds().getTransformedVertices());
        fixtureDef_gap.shape = shape_gap;
        fixtureDef_gap.filter.categoryBits = Config.CATEGORYBIT_BLOCKERGAP;
        fixtureDef_gap.filter.maskBits = Config.CATEGORYBIT_PLAYER;
        fixtureDef_gap.isSensor = true;
        fixture_gap = body.createFixture(fixtureDef_gap);
        BlockerFixtureUserData fixtureUserData_gap = new BlockerFixtureUserData(this, gameObjects.indexOf(this, false));
        fixture_gap.setUserData(fixtureUserData_gap);

        shape_gap.dispose();
    }
}

The player also has a similar method that does the same thing, just specified for the player.

 private void createFixture(boolean remove) {

    if (remove) {
        body.destroyFixture(fixture);
    }

    BodyDef bodyDef = new BodyDef();
    bodyDef.type = BodyDef.BodyType.DynamicBody;
    bodyDef.position.set(0, 0);
    body = world.createBody(bodyDef);
    FixtureDef fixtureDef = new FixtureDef();
    CircleShape circle = new CircleShape();
    circle.setRadius(getWidth() / 2);
    circle.setPosition(new Vector2(0, getY() + getHeight() / 2));
    fixtureDef.shape = circle;
    fixtureDef.filter.categoryBits = Config.CATEGORYBIT_PLAYER;
    fixture = body.createFixture(fixtureDef);

    circle.dispose();
}

The disposing of the world is in my main game class. But it's important to note (maybe?) that this game only has 1 screen as of right now.

If there is any additional information you may need, feel free to ask! Thanks a million!

My problem was that I was instantiating a body in the player createFixture method that is called every frame to edit the fixture sizes. I moved this to the constructor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM