Dicing things up a little

- Trying to slim this beauty down to a size 6.
- Shes a size 7.1
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-05 16:45:31 -04:00
1 parent d10d70a894
commit f2887632fe
50 files changed
+668 -491

No files matched your search

+52 -4
View File
@@ -1,3 +1,10 @@
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashSet;
@@ -6,8 +13,8 @@ import java.util.Set;
/**
* Reads the {@code CONSTANT_Class} entries of a class file. That is exactly the set of types the
* class links against - supertypes, field and method owners, casts, catches, constant class
* literals. Annotation types live in the annotation attributes as plain UTF-8 descriptors and are
* class names directly - supertypes, field and method owners, casts, catches, constant class
* literals. Field and method descriptors are also traversed to include signature-only types. Annotation types live in the annotation attributes as plain UTF-8 descriptors and are
* deliberately not reported: the JVM skips an annotation whose type is absent.
*/
public final class ClassReferences {
@@ -42,6 +49,7 @@ public final class ClassReferences {
int constantCount = readUnsignedShort(classFile, 8);
String[] utf8 = new String[constantCount];
List<Integer> classNameIndexes = new ArrayList<>();
List<Integer> descriptorIndexes = new ArrayList<>();
int offset = 10;
int index = 1;
while (index < constantCount) {
@@ -58,10 +66,18 @@ public final class ClassReferences {
classNameIndexes.add(readUnsignedShort(classFile, offset));
offset += 2;
}
case CONSTANT_STRING, CONSTANT_METHOD_TYPE, CONSTANT_MODULE, CONSTANT_PACKAGE -> offset += 2;
case CONSTANT_METHOD_TYPE -> {
descriptorIndexes.add(readUnsignedShort(classFile, offset));
offset += 2;
}
case CONSTANT_NAME_AND_TYPE -> {
descriptorIndexes.add(readUnsignedShort(classFile, offset + 2));
offset += 4;
}
case CONSTANT_STRING, CONSTANT_MODULE, CONSTANT_PACKAGE -> offset += 2;
case CONSTANT_METHOD_HANDLE -> offset += 3;
case CONSTANT_INTEGER, CONSTANT_FLOAT, CONSTANT_FIELDREF, CONSTANT_METHODREF,
CONSTANT_INTERFACE_METHODREF, CONSTANT_NAME_AND_TYPE, CONSTANT_DYNAMIC,
CONSTANT_INTERFACE_METHODREF, CONSTANT_DYNAMIC,
CONSTANT_INVOKE_DYNAMIC -> offset += 4;
case CONSTANT_LONG, CONSTANT_DOUBLE -> {
offset += 8;
@@ -83,9 +99,41 @@ public final class ClassReferences {
references.add(name);
}
}
for (int descriptorIndex : descriptorIndexes) {
addType(Type.getType(utf8[descriptorIndex]), references);
}
new ClassReader(classFile).accept(new ClassVisitor(Opcodes.ASM9) {
@Override
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
addType(Type.getType(descriptor), references);
return null;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature,
String[] exceptions) {
addType(Type.getMethodType(descriptor), references);
return null;
}
}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
return references;
}
private static void addType(Type type, Set<String> references) {
switch (type.getSort()) {
case Type.ARRAY -> addType(type.getElementType(), references);
case Type.OBJECT -> references.add(type.getInternalName());
case Type.METHOD -> {
addType(type.getReturnType(), references);
for (Type argument : type.getArgumentTypes()) {
addType(argument, references);
}
}
default -> {
}
}
}
private static String normalize(String rawName) {
if (rawName == null || rawName.isEmpty()) {
return null;
-121
View File
@@ -1,121 +0,0 @@
import org.apache.commons.compress.archivers.zip.ExtraFieldUtils;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.gradle.api.GradleException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.AtomicMoveNotSupportedException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public final class JarCompactor {
private static final int BUFFER_BYTES = 64 * 1024;
private JarCompactor() {
}
public static void compact(File artifact) {
if (artifact == null || !artifact.isFile()) {
throw new GradleException("Cannot compact missing jar artifact: " + artifact);
}
Path source = artifact.toPath();
Path temporary = null;
try {
temporary = Files.createTempFile(source.getParent(), artifact.getName(), ".compact");
rewrite(source, temporary);
replace(temporary, source);
} catch (IOException exception) {
if (temporary != null) {
try {
Files.deleteIfExists(temporary);
} catch (IOException cleanupFailure) {
exception.addSuppressed(cleanupFailure);
}
}
throw new GradleException("Unable to compact jar artifact " + artifact.getAbsolutePath(), exception);
}
}
private static void rewrite(Path source, Path destination) throws IOException {
byte[] buffer = new byte[BUFFER_BYTES];
try (ZipFile input = new ZipFile(source.toFile());
ZipArchiveOutputStream output = new ZipArchiveOutputStream(destination)) {
if (!output.isSeekable()) {
throw new IOException("Jar compaction requires seekable output.");
}
output.setLevel(9);
output.setUseZip64(Zip64Mode.Never);
output.setCreateUnicodeExtraFields(ZipArchiveOutputStream.UnicodeExtraFieldPolicy.NEVER);
Set<String> names = new HashSet<>();
Enumeration<? extends ZipEntry> entries = input.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if (entry.isDirectory()) {
continue;
}
if (!names.add(entry.getName())) {
throw new IOException("Duplicate jar entry: " + entry.getName());
}
output.putArchiveEntry(copyMetadata(entry));
copyEntry(input, output, entry, buffer);
output.closeArchiveEntry();
}
}
}
private static void copyEntry(ZipFile input, ZipArchiveOutputStream output, ZipEntry entry, byte[] buffer)
throws IOException {
CRC32 crc = new CRC32();
long size = 0L;
try (InputStream content = input.getInputStream(entry)) {
int read;
while ((read = content.read(buffer)) != -1) {
output.write(buffer, 0, read);
crc.update(buffer, 0, read);
size += read;
}
}
if (size != entry.getSize() || crc.getValue() != entry.getCrc()) {
throw new IOException("Jar entry failed size or CRC verification: " + entry.getName());
}
}
private static ZipArchiveEntry copyMetadata(ZipEntry source) throws IOException {
ZipArchiveEntry target = new ZipArchiveEntry(source.getName());
target.setMethod(ZipEntry.DEFLATED);
if (source.getTime() >= 0L) {
target.setTime(source.getTime());
}
if (source.getComment() != null) {
target.setComment(source.getComment());
}
if (source.getExtra() != null) {
target.setExtraFields(ExtraFieldUtils.parse(source.getExtra(), true,
ZipArchiveEntry.ExtraFieldParsingMode.BEST_EFFORT));
}
return target;
}
private static void replace(Path temporary, Path source) throws IOException {
try {
Files.move(
temporary,
source,
StandardCopyOption.ATOMIC_MOVE,
StandardCopyOption.REPLACE_EXISTING);
} catch (AtomicMoveNotSupportedException exception) {
Files.move(temporary, source, StandardCopyOption.REPLACE_EXISTING);
}
}
}