Tweak ZipDexContainer so it doesn't keep an open ZipFile

This commit is contained in:
Ben Gruver 2016-10-01 14:03:29 -07:00
parent ab20c37fd0
commit dbd9db303a
2 changed files with 65 additions and 62 deletions

View File

@ -41,6 +41,7 @@ import org.jf.dexlib2.dexbacked.OatFile;
import org.jf.dexlib2.dexbacked.OatFile.NotAnOatFileException; import org.jf.dexlib2.dexbacked.OatFile.NotAnOatFileException;
import org.jf.dexlib2.dexbacked.OatFile.OatDexFile; import org.jf.dexlib2.dexbacked.OatFile.OatDexFile;
import org.jf.dexlib2.dexbacked.ZipDexContainer; import org.jf.dexlib2.dexbacked.ZipDexContainer;
import org.jf.dexlib2.dexbacked.ZipDexContainer.NotAZipFileException;
import org.jf.dexlib2.iface.DexFile; import org.jf.dexlib2.iface.DexFile;
import org.jf.dexlib2.iface.MultiDexContainer; import org.jf.dexlib2.iface.MultiDexContainer;
import org.jf.dexlib2.writer.pool.DexPool; import org.jf.dexlib2.writer.pool.DexPool;
@ -50,7 +51,6 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.*; import java.io.*;
import java.util.List; import java.util.List;
import java.util.zip.ZipFile;
public final class DexFileFactory { public final class DexFileFactory {
@ -81,21 +81,12 @@ public final class DexFileFactory {
throw new DexFileNotFoundException("%s does not exist", file.getName()); throw new DexFileNotFoundException("%s does not exist", file.getName());
} }
ZipFile zipFile = null;
try {
zipFile = new ZipFile(file);
} catch (IOException ex) {
// ignore and continue
}
if (zipFile != null) { try {
ZipDexContainer container = new ZipDexContainer(zipFile, opcodes); ZipDexContainer container = new ZipDexContainer(file, opcodes);
try { return new DexEntryFinder(file.getPath(), container).findEntry("classes.dex", true);
return new DexEntryFinder(file.getPath(), container) } catch (NotAZipFileException ex) {
.findEntry("classes.dex", true); // eat it and continue
} finally {
container.close();
}
} }
InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
@ -188,20 +179,11 @@ public final class DexFileFactory {
throw new DexFileNotFoundException("Container file %s does not exist", file.getName()); throw new DexFileNotFoundException("Container file %s does not exist", file.getName());
} }
ZipFile zipFile = null;
try { try {
zipFile = new ZipFile(file); ZipDexContainer container = new ZipDexContainer(file, opcodes);
} catch (IOException ex) { return new DexEntryFinder(file.getPath(), container).findEntry(dexEntry, exactMatch);
// ignore and continue } catch (NotAZipFileException ex) {
} // eat it and continue
if (zipFile != null) {
ZipDexContainer container = new ZipDexContainer(zipFile, opcodes);
try {
return new DexEntryFinder(file.getPath(), container).findEntry(dexEntry, exactMatch);
} finally {
container.close();
}
} }
InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
@ -251,15 +233,9 @@ public final class DexFileFactory {
throw new DexFileNotFoundException("%s does not exist", file.getName()); throw new DexFileNotFoundException("%s does not exist", file.getName());
} }
ZipFile zipFile = null; ZipDexContainer zipDexContainer = new ZipDexContainer(file, opcodes);
try { if (zipDexContainer.isZipFile()) {
zipFile = new ZipFile(file); return zipDexContainer;
} catch (IOException ex) {
// ignore and continue
}
if (zipFile != null) {
return new ZipDexContainer(zipFile, opcodes);
} }
InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); InputStream inputStream = new BufferedInputStream(new FileInputStream(file));

View File

@ -40,8 +40,8 @@ import org.jf.dexlib2.iface.MultiDexContainer;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.Closeable;
import java.io.EOFException; import java.io.EOFException;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Enumeration; import java.util.Enumeration;
@ -54,19 +54,19 @@ import static org.jf.dexlib2.dexbacked.DexBackedDexFile.verifyMagicAndByteOrder;
/** /**
* Represents a zip file that contains dex files (i.e. an apk or jar file) * Represents a zip file that contains dex files (i.e. an apk or jar file)
*/ */
public class ZipDexContainer implements MultiDexContainer<ZipDexFile>, Closeable { public class ZipDexContainer implements MultiDexContainer<ZipDexFile> {
private final ZipFile zipFile; private final File zipFilePath;
private final Opcodes opcodes; private final Opcodes opcodes;
/** /**
* Constructs a new ZipDexContainer for the given zip file * Constructs a new ZipDexContainer for the given zip file
* *
* @param zipFile A Zip * @param zipFilePath The path to the zip file
* @param opcodes The Opcodes instance to use when loading dex files from this container * @param opcodes The Opcodes instance to use when loading dex files from this container
*/ */
public ZipDexContainer(@Nonnull ZipFile zipFile, @Nonnull Opcodes opcodes) { public ZipDexContainer(@Nonnull File zipFilePath, @Nonnull Opcodes opcodes) {
this.zipFile = zipFile; this.zipFilePath = zipFilePath;
this.opcodes = opcodes; this.opcodes = opcodes;
} }
@ -77,19 +77,24 @@ public class ZipDexContainer implements MultiDexContainer<ZipDexFile>, Closeable
*/ */
@Nonnull @Override public List<String> getDexEntryNames() throws IOException { @Nonnull @Override public List<String> getDexEntryNames() throws IOException {
List<String> entryNames = Lists.newArrayList(); List<String> entryNames = Lists.newArrayList();
Enumeration<? extends ZipEntry> entriesEnumeration = zipFile.entries(); ZipFile zipFile = getZipFile();
try {
Enumeration<? extends ZipEntry> entriesEnumeration = zipFile.entries();
while (entriesEnumeration.hasMoreElements()) { while (entriesEnumeration.hasMoreElements()) {
ZipEntry entry = entriesEnumeration.nextElement(); ZipEntry entry = entriesEnumeration.nextElement();
if (!isDex(entry)) { if (!isDex(zipFile, entry)) {
continue; continue;
}
entryNames.add(entry.getName());
} }
entryNames.add(entry.getName()); return entryNames;
} finally {
zipFile.close();
} }
return entryNames;
} }
/** /**
@ -100,16 +105,28 @@ public class ZipDexContainer implements MultiDexContainer<ZipDexFile>, Closeable
* @throws NotADexFile If the entry isn't a dex file * @throws NotADexFile If the entry isn't a dex file
*/ */
@Nullable @Override public ZipDexFile getEntry(@Nonnull String entryName) throws IOException { @Nullable @Override public ZipDexFile getEntry(@Nonnull String entryName) throws IOException {
ZipEntry entry = zipFile.getEntry(entryName); ZipFile zipFile = getZipFile();
if (entry == null) { try {
return null; ZipEntry entry = zipFile.getEntry(entryName);
} if (entry == null) {
return null;
}
return loadEntry(entry); return loadEntry(zipFile, entry);
} finally {
zipFile.close();
}
} }
@Override public void close() throws IOException { public boolean isZipFile() {
zipFile.close(); try {
getZipFile();
return true;
} catch (IOException ex) {
return false;
} catch (NotAZipFileException ex) {
return false;
}
} }
public class ZipDexFile extends DexBackedDexFile implements MultiDexContainer.MultiDexFile { public class ZipDexFile extends DexBackedDexFile implements MultiDexContainer.MultiDexFile {
@ -130,7 +147,7 @@ public class ZipDexContainer implements MultiDexContainer<ZipDexFile>, Closeable
} }
} }
private boolean isDex(@Nonnull ZipEntry zipEntry) throws IOException { private boolean isDex(@Nonnull ZipFile zipFile, @Nonnull ZipEntry zipEntry) throws IOException {
InputStream inputStream = zipFile.getInputStream(zipEntry); InputStream inputStream = zipFile.getInputStream(zipEntry);
try { try {
inputStream.mark(44); inputStream.mark(44);
@ -138,7 +155,7 @@ public class ZipDexContainer implements MultiDexContainer<ZipDexFile>, Closeable
try { try {
ByteStreams.readFully(inputStream, partialHeader); ByteStreams.readFully(inputStream, partialHeader);
} catch (EOFException ex) { } catch (EOFException ex) {
throw new NotADexFile("File is too short"); return false;
} }
try { try {
@ -152,9 +169,16 @@ public class ZipDexContainer implements MultiDexContainer<ZipDexFile>, Closeable
} }
} }
private ZipFile getZipFile() throws IOException {
try {
return new ZipFile(zipFilePath);
} catch (IOException ex) {
throw new NotAZipFileException();
}
}
@Nonnull @Nonnull
private ZipDexFile loadEntry(@Nonnull ZipEntry zipEntry) private ZipDexFile loadEntry(@Nonnull ZipFile zipFile, @Nonnull ZipEntry zipEntry) throws IOException {
throws IOException {
InputStream inputStream = zipFile.getInputStream(zipEntry); InputStream inputStream = zipFile.getInputStream(zipEntry);
try { try {
byte[] buf = ByteStreams.toByteArray(inputStream); byte[] buf = ByteStreams.toByteArray(inputStream);
@ -163,4 +187,7 @@ public class ZipDexContainer implements MultiDexContainer<ZipDexFile>, Closeable
inputStream.close(); inputStream.close();
} }
} }
public static class NotAZipFileException extends RuntimeException {
}
} }