From 670bf026d88cb7e5186e828ba3f7b704f5e63df7 Mon Sep 17 00:00:00 2001 From: Wyatt Gillette Date: Tue, 24 Jun 2025 21:54:57 +0200 Subject: [PATCH 1/2] Update BinaryExporter.java --- .../jme3/export/binary/BinaryExporter.java | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java b/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java index cdaf9abc17..c5332836e7 100644 --- a/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java +++ b/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2025 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +38,13 @@ import com.jme3.export.Savable; import com.jme3.export.SavableClassUtil; import com.jme3.math.FastMath; -import java.io.*; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.IdentityHashMap; @@ -116,32 +122,33 @@ * * @author Joshua Slack */ - public class BinaryExporter implements JmeExporter { - private static final Logger logger = Logger.getLogger(BinaryExporter.class - .getName()); + + private static final Logger logger = Logger.getLogger(BinaryExporter.class.getName()); protected int aliasCount = 1; protected int idCount = 1; - private final IdentityHashMap contentTable - = new IdentityHashMap<>(); - - protected HashMap locationTable - = new HashMap<>(); + private final IdentityHashMap contentTable = new IdentityHashMap<>(); + protected HashMap locationTable = new HashMap<>(); // key - class name, value = bco - private final HashMap classes - = new HashMap<>(); - + private final HashMap classes = new HashMap<>(); private final ArrayList contentKeys = new ArrayList<>(); public static boolean debug = false; - public static boolean useFastBufs = true; + /** + * Constructs a new {@code BinaryExporter}. + */ public BinaryExporter() { } + /** + * Returns a new instance of {@code BinaryExporter}. + * + * @return A new {@code BinaryExporter} instance. + */ public static BinaryExporter getInstance() { return new BinaryExporter(); } @@ -163,9 +170,11 @@ public static T saveAndLoad(AssetManager assetManager, T obj try { BinaryExporter exporter = new BinaryExporter(); exporter.save(object, baos); + BinaryImporter importer = new BinaryImporter(); importer.setAssetManager(assetManager); return (T) importer.load(baos.toByteArray()); + } catch (IOException ex) { // Should never happen. throw new AssertionError(ex); @@ -191,9 +200,7 @@ public void save(Savable object, OutputStream os) throws IOException { // write out tag table int classTableSize = 0; int classNum = classes.keySet().size(); - int aliasSize = ((int) FastMath.log(classNum, 256) + 1); // make all - // aliases a - // fixed width + int aliasSize = ((int) FastMath.log(classNum, 256) + 1); // make all aliases a fixed width os.write(ByteUtils.convertToBytes(classNum)); // 3. "number of classes" for (String key : classes.keySet()) { @@ -212,7 +219,7 @@ public void save(Savable object, OutputStream os) throws IOException { } classTableSize += 1 + bco.classHierarchyVersions.length * 4; - // write classname size & classname + // write class name size & class name byte[] classBytes = key.getBytes(); os.write(ByteUtils.convertToBytes(classBytes.length)); // 5. "full class-name size" os.write(classBytes); // 6. "full class name" @@ -286,17 +293,13 @@ public void save(Savable object, OutputStream os) throws IOException { // append stream to the output stream out.writeTo(os); - - out = null; - os = null; - if (debug) { - logger.fine("Stats:"); - logger.log(Level.FINE, "classes: {0}", classNum); - logger.log(Level.FINE, "class table: {0} bytes", classTableSize); - logger.log(Level.FINE, "objects: {0}", numLocations); - logger.log(Level.FINE, "location table: {0} bytes", locationTableSize); - logger.log(Level.FINE, "data: {0} bytes", location); + logger.log(Level.INFO, "BinaryExporter Stats:"); + logger.log(Level.INFO, "classes: {0}", classNum); + logger.log(Level.INFO, "class table: {0} bytes", classTableSize); + logger.log(Level.INFO, "objects: {0}", numLocations); + logger.log(Level.INFO, "location table: {0} bytes", locationTableSize); + logger.log(Level.INFO, "data: {0} bytes", location); } } @@ -305,14 +308,14 @@ private String getChunk(BinaryIdContentPair pair) { .getContent().bytes.length)); } - private int findPrevMatch(BinaryIdContentPair oldPair, - ArrayList bucket) { + private int findPrevMatch(BinaryIdContentPair oldPair, ArrayList bucket) { if (bucket == null) return -1; for (int x = bucket.size(); --x >= 0;) { BinaryIdContentPair pair = bucket.get(x); - if (pair.getContent().equals(oldPair.getContent())) + if (pair.getContent().equals(oldPair.getContent())) { return locationTable.get(pair.getId()); + } } return -1; } @@ -345,7 +348,7 @@ public OutputCapsule getCapsule(Savable object) { return contentTable.get(object).getContent(); } - private BinaryClassObject createClassObject(Class clazz) throws IOException{ + private BinaryClassObject createClassObject(Class clazz) throws IOException { BinaryClassObject bco = new BinaryClassObject(); bco.alias = generateTag(); bco.nameFields = new HashMap<>(); @@ -361,10 +364,10 @@ public int processBinarySavable(Savable object) throws IOException { return -1; } Class clazz = object.getClass(); - BinaryClassObject bco = classes.get(object.getClass().getName()); + BinaryClassObject bco = classes.get(clazz.getName()); // is this class been looked at before? in tagTable? if (bco == null) { - bco = createClassObject(object.getClass()); + bco = createClassObject(clazz); } // is object in contentTable? @@ -379,7 +382,6 @@ public int processBinarySavable(Savable object) throws IOException { object.write(this); newPair.getContent().finish(); return newPair.getId(); - } protected byte[] generateTag() { @@ -401,4 +403,4 @@ private BinaryIdContentPair generateIdContentPair(BinaryClassObject bco) { new BinaryOutputCapsule(this, bco)); return pair; } -} \ No newline at end of file +} From d5ac1f79aa74b06c7a75dfd7416d06d743b1a711 Mon Sep 17 00:00:00 2001 From: Wyatt Gillette Date: Wed, 25 Jun 2025 12:52:45 +0200 Subject: [PATCH 2/2] BinaryExporter: log messages --- .../jme3/export/binary/BinaryExporter.java | 30 +++++++++---------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java b/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java index c5332836e7..ede6f93fa1 100644 --- a/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java +++ b/jme3-core/src/plugins/java/com/jme3/export/binary/BinaryExporter.java @@ -155,7 +155,6 @@ public static BinaryExporter getInstance() { /** * Saves the object into memory then loads it from memory. - * * Used by tests to check if the persistence system is working. * * @param The type of savable. @@ -207,14 +206,13 @@ public void save(Savable object, OutputStream os) throws IOException { BinaryClassObject bco = classes.get(key); // write alias - byte[] aliasBytes = fixClassAlias(bco.alias, - aliasSize); + byte[] aliasBytes = fixClassAlias(bco.alias, aliasSize); os.write(aliasBytes); // 4. "class alias" classTableSize += aliasSize; // jME3 NEW: Write class hierarchy version numbers - os.write( bco.classHierarchyVersions.length ); - for (int version : bco.classHierarchyVersions){ + os.write(bco.classHierarchyVersions.length); + for (int version : bco.classHierarchyVersions) { os.write(ByteUtils.convertToBytes(version)); } classTableSize += 1 + bco.classHierarchyVersions.length * 4; @@ -243,14 +241,12 @@ public void save(Savable object, OutputStream os) throws IOException { // write out data to a separate stream int location = 0; // keep track of location for each piece - HashMap> alreadySaved = new HashMap<>( - contentTable.size()); + HashMap> alreadySaved = new HashMap<>(contentTable.size()); for (Savable savable : contentKeys) { // look back at previous written data for matches String savableName = savable.getClass().getName(); BinaryIdContentPair pair = contentTable.get(savable); - ArrayList bucket = alreadySaved - .get(savableName + getChunk(pair)); + ArrayList bucket = alreadySaved.get(savableName + getChunk(pair)); int prevLoc = findPrevMatch(pair, bucket); if (prevLoc != -1) { locationTable.put(pair.getId(), prevLoc); @@ -294,12 +290,13 @@ public void save(Savable object, OutputStream os) throws IOException { out.writeTo(os); if (debug) { - logger.log(Level.INFO, "BinaryExporter Stats:"); - logger.log(Level.INFO, "classes: {0}", classNum); - logger.log(Level.INFO, "class table: {0} bytes", classTableSize); - logger.log(Level.INFO, "objects: {0}", numLocations); - logger.log(Level.INFO, "location table: {0} bytes", locationTableSize); - logger.log(Level.INFO, "data: {0} bytes", location); + logger.log(Level.INFO, "BinaryExporter Stats:" + + "\n * Classes: {0}" + + "\n * Class Table: {1} bytes" + + "\n * Objects: {2}" + + "\n * Location Table: {3} bytes" + + "\n * Data: {4} bytes", + new Object[] {classNum, classTableSize, numLocations, locationTableSize, location}); } } @@ -309,8 +306,9 @@ private String getChunk(BinaryIdContentPair pair) { } private int findPrevMatch(BinaryIdContentPair oldPair, ArrayList bucket) { - if (bucket == null) + if (bucket == null) { return -1; + } for (int x = bucket.size(); --x >= 0;) { BinaryIdContentPair pair = bucket.get(x); if (pair.getContent().equals(oldPair.getContent())) {