10、Libgdx的内存管理

(官网:www.libgdx.cn

游戏是非常耗资源的应用。图片和音效可能耗费大量的内存,另一方面来说,这些资源没有被Java垃圾回收,让一个垃圾处理来决定将显存中的5M的图片进行释放也不是一个明知的选择。

我们希望尽可能的在生命周期内管理好我们的资源。在Libgdx中有多个类来表示这些资源。它们都统一继承一Disposable接口,这个类对需要释放的资源进行管理。释放资源失败将会导致内存泄漏。

这些类需要手动进行释放(可能不完整):

  • AssetManager
  • Bitmap
  • BitmapFont
  • BitmapFontCache
  • CameraGroupStrategy
  • DecalBatch
  • ETC1Data
  • FrameBuffer
  • Mesh
  • Model
  • ModelBatch
  • ParticleEffect
  • Pixmap
  • PixmapPacker
  • Shader
  • ShaderProgram
  • Shape
  • Skin
  • SpriteBatch
  • SpriteCache
  • Stage
  • Texture
  • TextureAtlas
  • TileAtlas
  • TileMapRenderer
  • com.badlogic.gdx.physics.box2d.World
  • 所有的bullet类

资源文件要在不使用是尽快的释放,访问释放的资源将会导致错误。要确保这样的事情不要发生。

要判断一个特定的类是否需要释放,可以看一下它有没有disposed()方法,如果有,则需要释放。

对象轮询

对象轮询是重复利用未激活或者“死掉”的对象的基本原则,而不是每次都创建新的对象。可以通过创建一个对象池来完成,当你需要一个新的对象是,你可以从对象池中获取。如果池中有可用的对象,就返回,如果池是空的或者不包含可用的对象,将会创建一个新的对象的实例并返回。当你不需要一个对象时,需要进行释放,这就意味着将对象返回到池中。通过这种方式达到分配内存的重复利用。

这在游戏的内存管理中至关重要。

Libgdx提供了一系列的工具来实现简单的轮询。

  • Poolable接口
  • Pool
  • Pools

    继承Poolable接口意味着你需要在你的对象中有一个reset()方法。这个方法可以自动调用释放你的对象。

以下是一个简单的示例:

 public class Bullet implements Poolable {
public Vector2 position;
public boolean alive;
/**
 * 构造器,初始化.
 */
public Bullet() {
    this.position = new Vector2();
    this.alive = false;
}
/**
 * 初始化,从对象池中获取
 */
public void init(float posX, float posY) {
    position.set(posX,  posY);
    alive = true;
}
/**
 * 回调方法
 */
@Override
public void reset() {
    position.set(0,0);
    alive = false;
}
/**
 *更新
 */
public void update (float delta) {
    // 更新位置
    position.add(1*delta*60, 1*delta*60);
    // 屏幕之外,设置为dead
    if (isOutOfScreen()) alive = false;
}

}

在游戏的world类中:

public class World {
// Bullet类
private final Array<Bullet> activeBullets = new Array<Bullet>();
// bullet池
private final Pool<Bullet> bulletPool = new Pool<Bullet>() {
@Override
protected Bullet newObject() {
    return new Bullet();
}
};

public void update(float delta) {
    // 新的Bullet
    Bullet item = bulletPool.obtain();
    item.init(2, 2);
    activeBullets.add(item);
    //释放bullet
    Bullet item;
    int len = activeBullets.size;
    for (int i = len; --i >= 0;) {
        item = activeBullets.get(i);
        if (item.alive == false) {
            activeBullets.removeIndex(i);
            bulletPool.free(item);
        }
    }
}

}

Pools类中提供了静态方法来动态的创建任何对象的池。如下:

private final Pool<Bullet> bulletPool = Pools.get(Bullet.class);

怎样使用Pool

一个Pool<>管理一个单独类型的对象。从一个特定的Pool实例中取出,然后释放之后返回到Pool中。对象可能会实现Poolable接口,这将会在对象返回到Pool中自动进行重置。对象将按需分配。

你必须实现你自己的Pool<>子类,因为newObject方法是抽象的。

www.libgdx.cn版权所有,如需转载,注明出处)

时间: 2024-10-12 13:12:46

10、Libgdx的内存管理的相关文章

【翻译】《深入解析windows操作系统第6版下册》第10章:内存管理

[翻译]<深入解析windows操作系统第6版下册>第10章:内存管理(第一部分) [翻译]<深入解析windows操作系统第6版下册>第10章:内存管理(第二部分) [翻译]<深入解析windows操作系统第6版下册>第10章:内存管理(第三部分) . . .

深入理解_JVM内存管理调优案例分析与实战10

1.高性能硬件上的程序部署策略 目前常用2种方式: (1)通过64位JDK来使用大内存: 使用第一种方式关键: <1>控制应用程序的Full GC频率.譬如10多个小时甚至一天才出现一次Full GC. 关键:大多数对象的生存时间不应该太长,保证老年代空间的稳定. 在大多数网站形势的应用里,主要对象的生存周期都是请求级或页面级的,会话级和全局级的长生命对象相对较少,控制住Full GC. 需要考虑的问题: <1>内存回收导致的长时间停顿: <2>现阶段,64位JDK的性

内存管理(16.5.10)

Cocoa中的内存管理机制: 每一个对象都有一个引用计数(retain count): 对象被创建的时候,引用计数的值是1: 当引用计数值是0的时候,系统会调用自己的dealloc方法将对象销毁: retainCount 用来打印当前的引用计数/ 内存管理原则: 内存管理就是最终的引用计数要平衡,如果最后引用计数大于0则会内存泄漏,如果引用计数等于0还对该对象进行操作,则会出现内存访问失败,程序闪退,所以应设置为nil. IOS对象都继承于NSObject,改对象有一个retainCount来显

内存管理扩展(16.5.10)

iPhone/Mac Objective-C内存管理教程和原理剖析 前言 初学objectice-C的朋友都有一个困惑,总觉得对objective-C的内存管理机制琢磨不透,程序经常内存泄漏或莫名其妙的崩溃.我在这里总结了自己对objective-C内存管理机制的研究成果和经验,写了这么一个由浅入深的教程.希望对大家有所帮助,也欢迎大家一起探讨. 此文涉及的内存管理是针对于继承于NSObject的Class.一 基本原理Objective-C的内存管理机制与.Net/Java那种全自动的 垃圾回

Linux内存管理 (10)缺页中断处理【转】

转自:https://www.cnblogs.com/arnoldlu/p/8335475.html 专题:Linux内存管理专题 关键词:数据异常.缺页中断.匿名页面.文件映射页面.写时复制页面.swap页面. malloc()和mmap()等内存分配函数,在分配时只是建立了进程虚拟地址空间,并没有分配虚拟内存对应的物理内存. 当进程访问这些没有建立映射关系的虚拟内存时,处理器自动触发一个缺页异常. 缺页异常是Linux内存管理中最复杂和重要的一部分,需要考虑很多相关细节,包括匿名页面.KSM

linux内存管理

一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程序可调用它.假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段.     2) 数据段:存放已初始化的全局变量.静态变量(包括全局和局部的).常量.static全局变量和static函数只能在当前文件中被调用.     3) 未初始化数据区(uninitializeddata s

Block内存管理实例分析

在ios开发中,相信说道block大家都不陌生,内存管理问题也是开发者最头疼的问题,网上很多讲block的博客,但大都是理论性多点,今天结合一些实例来讲解下. 存储域 首先和大家聊聊block的存储域,根据block在内存中的位置,block被分为三种类型: NSGlobalBlock NSStackBlock NSMallocBlock 从字面意思上大家也可以看出来 NSGlobalBlock是位于全局区的block,它是设置在程序的数据区域(.data区)中. NSStackBlock是位于

c++ 块内存管理

#pragma once   //头文件 #include<iostream> #include<string.h> #include<list> #include "TypeTraits.hpp"  //类型萃取 #include <stdarg.h> using namespace std; struct SaveAdapter//保存适配器 基类 { virtual void save(const char* fmt, ...) =

魏兆辉的IOS基础学习笔记之十二 OC语言基础-07 Foundation内存管理

本篇博文,将给大家介绍下再Objective-C中如何使用内存管理.一个程序运行的时候,如果不及时的释放没有用的空间内存.那么,程序会越来 越臃肿,内存占用量会不断升高.我们在使用的时候,就会感觉很卡,最终使得程序运行奔溃.因此,将无效的内存及时清理释放,是非常有必要的. 一个对象在最初创建使用,到最后的回收释放,经历的是怎样一个过程呢?包括:诞生(通过alloc或new方法实现).生存(接收消息并执行操作).交友(通过复合以及向方法传递参数).最终死去(被释放掉). 一.引用计数 在对象创建的