I use the bytecode library known as ASM to modify class files, and then I want to write each class file back to the jar file, and not to the folder filled with class files. I do this by running this code:
My problem occurs when a ZipException is thrown for an not expected size, i.e.
java.util.zip.ZipException: invalid entry compressed size (expected 695 but got 693 bytes) at java.util.zip.ZipOutputStream.closeEntry(Unknown Source) at org.steinburg.client.accessor.Accessor.accessJar(Accessor.java:64) at org.steinburg.client.accessor.Accessor.<init>(Accessor.java:41) at Loader.main(Loader.java:5) package org.steinburg.client.accessor; import java.io.DataInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; public class Accessor { private String input; private File inFile; private JarEntry jarEntry; private JarFile jarFile; private Enumeration<JarEntry> entries; private InputStream is; private String out; private File outFile; private FileOutputStream fos; private JarOutputStream jos; private byte[] bytes; public Accessor(){ try{ input = new String("Input Jar.jar"); inFile = new File(input); jarFile = new JarFile(inFile); entries = jarFile.entries(); out = new String("Output Jar.jar"); outFile = new File(out); fos = new FileOutputStream(outFile); jos = new JarOutputStream(fos); accessJar(); } catch (Exception e) { e.printStackTrace(); } } protected final void accessJar(){ try { while (entries.hasMoreElements()){ jarEntry = entries.nextElement(); is = jarFile.getInputStream(jarEntry); if (jarEntry.getName().endsWith(".class")){ ClassReader cr = new ClassReader(is); ClassWriter cw = new ClassWriter(cr, 0); FieldAdapter fa = new FieldAdapter(cw); cr.accept(fa, 0); bytes = cw.toByteArray(); } else { bytes = readBytes(is); } JarEntry je = new JarEntry(jarEntry); jos.putNextEntry(je); jos.write(bytes); jos.closeEntry(); } jos.close(); } catch (Exception e) { e.printStackTrace(); } } protected byte[] readBytes(InputStream inputStream){ try{ DataInputStream reader = new DataInputStream(inputStream); byte[] toReturn = new byte[reader.available()]; reader.readFully(toReturn); reader.close(); return toReturn; } catch (Exception e){ e.printStackTrace(); return null; } } }
ClassReader, ClassWriter (each part of the library) and FieldAdapter (made by me) simply despise the code, and to get the bytes of the whole class I use cw.toByteArray (). There is no problem how to manipulate bytecode, it is just writing to a new jar file via JarOutputStream. Does anyone know how to solve this problem?
source share