Ответ 1
Вы попробовали вырезанную версию кода "box2d only", который вы опубликовали, чтобы узнать, есть ли у него такая же проблема? Причина, по которой я спрашиваю, заключается в том, что вы также разместили еще один вопрос о "изменении свойств FixtureDef" в изменении свойств FixtureDef Java Libgdx, и вы указали намного больше своего общего кода. (Код из этого вопроса является подмножеством кода из другого вопроса). Если посмотреть на этот код, могут возникнуть некоторые проблемы.
В другом вопросе вы помещаете тела, bodyDefs, fixtures и fixtureDefs в HashMap, вы не показываете, как вы извлекаете/очищаете карту. Это может привести к утечке памяти. Я бы сказал, скорее всего, нет, но вы никогда не знаете.
Но я видел этот бит, который, я уверен, вызовет проблемы:
public void attachNewSprite(String internalPath){
entitySprite = new Sprite(new Texture(Gdx.files.internal(internalPath)));
((Body)bodyObjects.get(BodyReferences.BODY)).setUserData(entitySprite);
}
В этом вопросе вы сказали, что вы не использовали спрайтов, но если вы сделаете что-то выше в своем коде, каждая новая текстура() займет память. Вы должны явно распоряжаться каждой создаваемой текстурой. Вы не должны создавать новую текстуру каждый раз, когда вы создаете новый Sprite. В идеале вы создаете текстуру один раз, затем используйте Sprite, который является TextureRegion, для отображения текстуры. Затем удалите текстуру, когда все закончите (в конце уровня/игры/etc). Чтобы избавиться от текстуры, вам нужно будет ссылаться на нее.
Edit/Update:
У меня было какое-то время этим утром, поэтому я взял ваш опубликованный код и немного добавил для создания простого простого приложения с созданием тела и кодом удаления тела. Я настраиваю таймер, чтобы стрелять каждые X секунд, чтобы увидеть, что происходит, когда вы создаете/уничтожаете тела 10k, и код, который вы опубликовали, выглядит отлично. Поэтому я думаю, что ваша проблема может быть в другом месте с кодом, который вы не опубликовали. Память на моей машине будет немного изменяться (вы никогда не знаете, когда GC встретятся, но она никогда не превысила 45 МБ).
Если вы не видите что-то другое ниже, чем то, что вы делаете (или если у вас больше кодов для публикации и т.д.), я не вижу проблемы с тем, что вы поделили до сих пор.
import java.util.concurrent.ThreadLocalRandom;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.Timer.Task;
public class Memory implements ApplicationListener {
private static World world;
private static void createNewBodies(boolean isCircle, Vector2 position, Vector2 dimensions) {
BodyDef bodyDef = new BodyDef();
//bodyDef.type = type; //all bodies here are dynamic
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(position);
Body body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
Fixture fixture;
if(isCircle){
CircleShape circle = new CircleShape();
circle.setRadius(dimensions.x);
fixtureDef.shape = circle;
fixture = body.createFixture(fixtureDef);
circle.dispose();
}else{
PolygonShape rectangle = new PolygonShape();
rectangle.setAsBox(dimensions.x, dimensions.y);
fixtureDef.shape = rectangle;
fixture = body.createFixture(fixtureDef);
rectangle.dispose();
}
}
public static void disposeAllBodies(){
Array<Body> bodies = new Array<Body>();
world.getBodies(bodies);
int destroyCount = 0;
System.out.println("Attempting to destroy " + world.getBodyCount()+ " bodies");
for(Body b : bodies){
world.destroyBody(b);
destroyCount++;
}
System.out.println("Successfully destroyed " + destroyCount + " body(s), " + world.getBodyCount() + " remain");
}
private static void buildAllBodies() {
int minPos = 10;
int maxPos = 400;
int minWidthHeight = 50;
Vector2 position = new Vector2();
Vector2 dimensions = new Vector2();
for (int i=0; i<10000; i=i+2) {
position.x = ThreadLocalRandom.current().nextInt(minPos, maxPos+1);
position.y = ThreadLocalRandom.current().nextInt(minPos*2, maxPos*2+1);
dimensions.x = ThreadLocalRandom.current().nextInt(minWidthHeight, minWidthHeight+1);
dimensions.y = dimensions.x;
createNewBodies(true, position, dimensions);
createNewBodies(false, position, dimensions);
}
}
@Override
public void create() {
world = new World ( new Vector2(0.0f, -9.8f), true);
Timer.schedule(new Task() {
@Override
public void run() {
buildAllBodies();
disposeAllBodies();
}
}
, 1.0f
, 10.0f //how often to do the cycle (in seconds)
);
}
@Override
public void render() { }
@Override
public void dispose() {
world.dispose();
}
@Override
public void resize(int width, int height) { }
@Override
public void pause() { }
@Override
public void resume() { }
}