优化 mod 列表加载速度 (#1985)

* Share ZipFileSystem

* fix memory leak
This commit is contained in:
Glavo 2023-01-08 18:15:55 +08:00 committed by GitHub
parent bf822d7cf7
commit 1cc429c7ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 88 deletions

View File

@ -21,7 +21,6 @@ import com.google.gson.*;
import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.JsonAdapter;
import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.IOException; import java.io.IOException;
@ -58,8 +57,7 @@ public final class FabricModMetadata {
this.contact = contact; this.contact = contact;
} }
public static LocalModFile fromFile(ModManager modManager, Path modFile) throws IOException, JsonParseException { public static LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile)) {
Path mcmod = fs.getPath("fabric.mod.json"); Path mcmod = fs.getPath("fabric.mod.json");
if (Files.notExists(mcmod)) if (Files.notExists(mcmod))
throw new IOException("File " + modFile + " is not a Fabric mod."); throw new IOException("File " + modFile + " is not a Fabric mod.");
@ -68,7 +66,6 @@ public final class FabricModMetadata {
return new LocalModFile(modManager, modManager.getLocalMod(metadata.id, ModLoaderType.FABRIC), modFile, metadata.name, new LocalModFile.Description(metadata.description), return new LocalModFile(modManager, modManager.getLocalMod(metadata.id, ModLoaderType.FABRIC), modFile, metadata.name, new LocalModFile.Description(metadata.description),
authors, metadata.version, "", metadata.contact != null ? metadata.contact.getOrDefault("homepage", "") : "", metadata.icon); authors, metadata.version, "", metadata.contact != null ? metadata.contact.getOrDefault("homepage", "") : "", metadata.icon);
} }
}
@JsonAdapter(FabricModAuthorSerializer.class) @JsonAdapter(FabricModAuthorSerializer.class)
public static final class FabricModAuthor { public static final class FabricModAuthor {

View File

@ -3,10 +3,10 @@ package org.jackhuang.hmcl.mod;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import com.moandjiezana.toml.Toml; import com.moandjiezana.toml.Toml;
import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystem; import java.nio.file.FileSystem;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -115,8 +115,7 @@ public final class ForgeNewModMetadata {
} }
} }
public static LocalModFile fromFile(ModManager modManager, Path modFile) throws IOException, JsonParseException { public static LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile)) {
Path modstoml = fs.getPath("META-INF/mods.toml"); Path modstoml = fs.getPath("META-INF/mods.toml");
if (Files.notExists(modstoml)) if (Files.notExists(modstoml))
throw new IOException("File " + modFile + " is not a Forge 1.13+ mod."); throw new IOException("File " + modFile + " is not a Forge 1.13+ mod.");
@ -127,8 +126,8 @@ public final class ForgeNewModMetadata {
Path manifestMF = fs.getPath("META-INF/MANIFEST.MF"); Path manifestMF = fs.getPath("META-INF/MANIFEST.MF");
String jarVersion = ""; String jarVersion = "";
if (Files.exists(manifestMF)) { if (Files.exists(manifestMF)) {
try { try (InputStream is = Files.newInputStream(manifestMF)) {
Manifest manifest = new Manifest(Files.newInputStream(manifestMF)); Manifest manifest = new Manifest(is);
jarVersion = manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION); jarVersion = manifest.getMainAttributes().getValue(Attributes.Name.IMPLEMENTATION_VERSION);
} catch (IOException e) { } catch (IOException e) {
LOG.log(Level.WARNING, "Failed to parse MANIFEST.MF in file " + modFile); LOG.log(Level.WARNING, "Failed to parse MANIFEST.MF in file " + modFile);
@ -139,5 +138,4 @@ public final class ForgeNewModMetadata {
mod.getDisplayURL(), mod.getDisplayURL(),
metadata.getLogoFile()); metadata.getLogoFile());
} }
}
} }

View File

@ -23,7 +23,6 @@ import com.google.gson.reflect.TypeToken;
import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.IOException; import java.io.IOException;
@ -120,8 +119,7 @@ public final class ForgeOldModMetadata {
return authors; return authors;
} }
public static LocalModFile fromFile(ModManager modManager, Path modFile) throws IOException, JsonParseException { public static LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile)) {
Path mcmod = fs.getPath("mcmod.info"); Path mcmod = fs.getPath("mcmod.info");
if (Files.notExists(mcmod)) if (Files.notExists(mcmod))
throw new IOException("File " + modFile + " is not a Forge mod."); throw new IOException("File " + modFile + " is not a Forge mod.");
@ -143,5 +141,4 @@ public final class ForgeOldModMetadata {
StringUtils.isBlank(metadata.getUrl()) ? metadata.getUpdateUrl() : metadata.url, StringUtils.isBlank(metadata.getUrl()) ? metadata.getUpdateUrl() : metadata.url,
metadata.getLogoFile()); metadata.getLogoFile());
} }
}
} }

View File

@ -73,25 +73,28 @@ public final class ModManager {
String fileName = StringUtils.removeSuffix(FileUtils.getName(modFile), DISABLED_EXTENSION, OLD_EXTENSION); String fileName = StringUtils.removeSuffix(FileUtils.getName(modFile), DISABLED_EXTENSION, OLD_EXTENSION);
String description; String description;
if (fileName.endsWith(".zip") || fileName.endsWith(".jar")) { if (fileName.endsWith(".zip") || fileName.endsWith(".jar")) {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile)) {
try { try {
return ForgeOldModMetadata.fromFile(this, modFile); return ForgeOldModMetadata.fromFile(this, modFile, fs);
} catch (Exception ignore) { } catch (Exception ignore) {
} }
try { try {
return ForgeNewModMetadata.fromFile(this, modFile); return ForgeNewModMetadata.fromFile(this, modFile, fs);
} catch (Exception ignore) { } catch (Exception ignore) {
} }
try { try {
return FabricModMetadata.fromFile(this, modFile); return FabricModMetadata.fromFile(this, modFile, fs);
} catch (Exception ignore) { } catch (Exception ignore) {
} }
try { try {
return PackMcMeta.fromFile(this, modFile); return PackMcMeta.fromFile(this, modFile, fs);
} catch (Exception ignore) { } catch (Exception ignore) {
} }
} catch (Exception ignored) {
}
description = ""; description = "";
} else if (fileName.endsWith(".litemod")) { } else if (fileName.endsWith(".litemod")) {

View File

@ -23,7 +23,6 @@ import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.Immutable; import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.gson.Validation; import org.jackhuang.hmcl.util.gson.Validation;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.IOException; import java.io.IOException;
@ -143,8 +142,7 @@ public class PackMcMeta implements Validation {
} }
} }
public static LocalModFile fromFile(ModManager modManager, Path modFile) throws IOException, JsonParseException { public static LocalModFile fromFile(ModManager modManager, Path modFile, FileSystem fs) throws IOException, JsonParseException {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile)) {
Path mcmod = fs.getPath("pack.mcmeta"); Path mcmod = fs.getPath("pack.mcmeta");
if (Files.notExists(mcmod)) if (Files.notExists(mcmod))
throw new IOException("File " + modFile + " is not a resource pack."); throw new IOException("File " + modFile + " is not a resource pack.");
@ -157,5 +155,4 @@ public class PackMcMeta implements Validation {
metadata.pack.description, metadata.pack.description,
"", "", "", "", ""); "", "", "", "", "");
} }
}
} }