libgdx-collections-json — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited libgdx-collections-json (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Quick reference for com.badlogic.gdx.utils.* — libGDX's GC-friendly collections, object pooling, JSON serialization, and utility classes. These replace java.util.* equivalents to reduce garbage collection pressure, especially on Android.
Array<String> arr = new Array<>(); // also: new Array<>(capacity), new Array<>(ordered, capacity)Public fields: T[] items (backing array), int size (element count), boolean ordered.
Key methods: add, get, set, insert, swap, pop, peek, first, clear, sort, reverse, shuffle, truncate, shrink, ensureCapacity, isEmpty, notEmpty, select(predicate).
CRITICAL — identity parameter required: removeValue(item, identity), contains(item, identity), indexOf(item, identity), lastIndexOf(item, identity). identity=true uses ==, identity=false uses .equals(). There is no single-argument overload.
There is NO `remove(Object)` method. It is removeValue(value, identity) or removeIndex(int).
Gotchas:
items array may be larger than size — iterate with for (int i = 0; i < arr.size; i++), never items.length.items[i] past size contains stale references — always check i < size.for-each iteration. Use DelayedRemovalArray, SnapshotArray, or manual index loop.ordered is false, removeIndex() swaps the last element into the gap (O(1)) instead of shifting (O(n)).Both wrap begin()/end() around iteration. DelayedRemovalArray queues removals during iteration, applies at end() (returns void from begin()). SnapshotArray takes a snapshot; begin() returns T[] to iterate, modifications go to a copy. Both support nested begin()/end(). Used internally by Scene2D.
ObjectMap<String, Integer> map = new ObjectMap<>();
map.put("hp", 100); // returns old value or null
map.get("hp"); map.get("hp", 0); // null or default
map.remove("hp"); map.containsKey("hp");
map.containsValue(100, false); // identity param on values toosize is a public field (not a method). Iterate via for (Entry e : map), map.keys(), map.values(), or map.entries().
Gotchas:
next() call. Do not store entry references.Collections.allocateIterators = false). Nested iteration on the same map throws GdxRuntimeException. Set Collections.allocateIterators = true if needed.entries(), keys(), values() (libGDX iterator types).OrderedMap\<K,V\> — extends ObjectMap, maintains insertion order. orderedKeys() returns internal Array<K>.
IntMap<V>, LongMap<V> — object values, get() returns null if missing. IntIntMap, ObjectIntMap<K>, ObjectFloatMap<K> — primitive values, `get()` MUST provide default (no null for primitives). ObjectIntMap has getAndIncrement(key, defaultValue, increment).
Primitive-value maps: put() returns void (not old value). Use put(key, value, defaultValue) overload to get old value.
ObjectSet<T> — add, remove, contains (NO identity param, unlike Array). first() throws if empty. OrderedSet<T> — maintains insertion order, orderedItems() returns internal Array<T>. IntSet — primitive int, does NOT implement Iterable. size is a public field on all sets.
addLast/addFirst, removeFirst/removeLast, first()/last() (peek), get(index). size is a public field.
Pool<T> is abstract — override newObject(). Methods: obtain(), free(obj) (calls reset() if Pool.Poolable), fill(n), getFree(), clear(). Constructor: Pool(initialCapacity, max).
DefaultPool\<T\> (since 1.13.5) — preferred. Uses supplier: new DefaultPool<>(Bullet::new) or new DefaultPool<>(Bullet::new, 16, 100). No reflection, GWT-safe.
Implement Pool.Poolable for automatic reset() on free().
PoolManager pools = new PoolManager();
pools.addPool(Bullet.class, Bullet::new); // or pass a Pool directly
Bullet b = pools.obtain(Bullet.class);
pools.free(b); // looks up pool by object's classDefaultPool.DefaultPool or PoolManager.Json json = new Json();
json.setOutputType(JsonWriter.OutputType.json); // json | javascript | minimal
json.setIgnoreUnknownFields(true); // don't fail on extra fields
json.setUsePrototypes(false); // write all fields, not just changed
String str = json.toJson(myObject); // serialize
MyClass obj = json.fromJson(MyClass.class, jsonStr); // deserialize (also accepts FileHandle)There is no `Json.parse()` method. Use JsonReader for raw parsing or Json.fromJson() for typed deserialization.
Custom serializer: json.setSerializer(MyClass.class, new Json.Serializer<MyClass>() { ... }) — implement write(Json, T, Class) and read(Json, JsonValue, Class).
new JsonReader().parse(fileHandle) or .parse(string) returns JsonValue tree.
Navigation: get("name") / get(index) returns child JsonValue (null if not found). has("name"), size (public field). Type checks: isObject(), isArray(), isString(), isNumber(), isBoolean(), isNull().
*`as vs get` — CRITICAL distinction:*
asString(), asInt(), asFloat(), asBoolean() — converts THIS node's value.getString("name"), getInt("hp") — finds child by name, returns its value. Throws IllegalArgumentException if child not found. Use getString("name", "default") for safe defaults.Iterate children: for (JsonValue entry : root) { entry.name; entry.asString(); } or for (JsonValue c = root.child; c != null; c = c.next).
I18NBundle.createBundle(fileHandle) or createBundle(fileHandle, locale). Methods: get("key"), format("key", args...). Resolution: messages_de_DE.properties → messages_de.properties → messages.properties.
There is no `I18NBundle.load()` — use the static factory I18NBundle.createBundle().
// Static convenience (uses global Timer.instance())
Timer.schedule(new Timer.Task() {
public void run() { /* runs on GL thread */ }
}, 2f); // delay seconds
Timer.schedule(task, 1f, 0.5f); // delay, then repeat every 0.5s forever
Timer.schedule(task, 1f, 0.5f, 5); // delay, interval, repeatCount
task.cancel(); // cancel a scheduled task
task.isScheduled(); // booleanTimer.Task is abstract — override run(). `run()` executes on the GL/render thread (posted via Gdx.app.postRunnable()), safe for libGDX API calls.
Instance methods use scheduleTask(task, ...) (not schedule). The timer also has stop(), start(), clear().
TimeUtils:
long start = TimeUtils.nanoTime();
// ... work ...
long elapsed = TimeUtils.timeSinceNanos(start); // nanoTime() - start
long ms = TimeUtils.millis(); // System.currentTimeMillis()
long elapsedMs = TimeUtils.timeSinceMillis(startMs);Align — bit-flag constants for layout alignment:
Align.center // 1 Align.topLeft // top|left
Align.top // 2 Align.topRight // top|right
Align.bottom // 4 Align.bottomLeft // bottom|left
Align.left // 8 Align.bottomRight // bottom|right
Align.right // 16Scaling — abstract class with static instances (NOT an enum): Scaling.fit, Scaling.fill, Scaling.contain, Scaling.stretch, Scaling.fillX, Scaling.fillY, Scaling.stretchX, Scaling.stretchY, Scaling.none.
AsyncExecutor — simple thread pool:
AsyncExecutor executor = new AsyncExecutor(4); // 4 threads
AsyncResult<String> result = executor.submit(() -> computeExpensiveThing());
if (result.isDone()) {
String value = result.get(); // blocks if not done, throws on error
}
executor.dispose(); // MUST disposeAsyncTask<T> interface has a single T call() method. Executor must be disposed.
ScreenUtils:
ScreenUtils.clear(0, 0, 0, 1); // r, g, b, a
ScreenUtils.clear(Color.BLACK);
ScreenUtils.clear(0, 0, 0, 1, true); // also clear depth bufferlibGDX collections are GWT-compatible while many java.util features are not. Prefer libGDX collections in cross-platform projects. For reflection on GWT, use com.badlogic.gdx.utils.reflect.* instead of java.lang.reflect.*.
Array, ObjectMap, ObjectSet instead. libGDX collections reduce GC pressure and are GWT-compatible.Array.contains(), indexOf(), removeValue(), and ObjectMap.containsValue() require a boolean identity parameter. true = use ==, false = use .equals(). There is no single-argument overload.items.length is the backing array capacity. Elements past size are stale. Always use size.removeValue(object, identity) or removeIndex(int).map.entries(), map.keys(), map.values(), or for (Entry e : map) directly. Same Entry instance is reused each iteration — do not store references.GdxRuntimeException. Set Collections.allocateIterators = true to allow it.new DefaultPool<>(MyClass::new) for local pools or PoolManager for shared pools.JsonReader.parse() for raw JsonValue tree, or Json.fromJson() for typed deserialization.getString("name") finds a child named "name" and returns its string value. asString() returns THIS node's value. Calling getString() on a node without matching children throws IllegalArgumentException.Timer.Task.run() executes on the GL/render thread via postRunnable(). Safe for libGDX API calls but do not block it.I18NBundle.createBundle().~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.