Cleanup (I/O ops in java-decompiler)

master
Roman Shevchenko 9 years ago
parent 5795c1d9e0
commit 23da5d99d2
  1. 38
      src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java
  2. 10
      src/org/jetbrains/java/decompiler/struct/ContextUnit.java
  3. 29
      src/org/jetbrains/java/decompiler/struct/StructContext.java
  4. 10
      src/org/jetbrains/java/decompiler/struct/StructMember.java
  5. 31
      src/org/jetbrains/java/decompiler/struct/lazy/LazyLoader.java
  6. 31
      src/org/jetbrains/java/decompiler/util/DataInputFullStream.java
  7. 64
      src/org/jetbrains/java/decompiler/util/InterpreterUtil.java
  8. 26
      test/org/jetbrains/java/decompiler/BulkDecompilationTest.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2015 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -150,17 +150,11 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
return InterpreterUtil.getBytes(file); return InterpreterUtil.getBytes(file);
} }
else { else {
ZipFile archive = new ZipFile(file); try (ZipFile archive = new ZipFile(file)) {
try {
ZipEntry entry = archive.getEntry(internalPath); ZipEntry entry = archive.getEntry(internalPath);
if (entry == null) { if (entry == null) throw new IOException("Entry not found: " + internalPath);
throw new IOException("Entry not found: " + internalPath);
}
return InterpreterUtil.getBytes(archive, entry); return InterpreterUtil.getBytes(archive, entry);
} }
finally {
archive.close();
}
} }
} }
@ -193,14 +187,8 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
@Override @Override
public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) { public void saveClassFile(String path, String qualifiedName, String entryName, String content, int[] mapping) {
File file = new File(getAbsolutePath(path), entryName); File file = new File(getAbsolutePath(path), entryName);
try { try (Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF8")) {
Writer out = new OutputStreamWriter(new FileOutputStream(file), "UTF8"); out.write(content);
try {
out.write(content);
}
finally {
out.close();
}
} }
catch (IOException ex) { catch (IOException ex) {
DecompilerContext.getLogger().writeMessage("Cannot write class file " + file, ex); DecompilerContext.getLogger().writeMessage("Cannot write class file " + file, ex);
@ -238,21 +226,15 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
return; return;
} }
try { try (ZipFile srcArchive = new ZipFile(new File(source))) {
ZipFile srcArchive = new ZipFile(new File(source)); ZipEntry entry = srcArchive.getEntry(entryName);
try { if (entry != null) {
ZipEntry entry = srcArchive.getEntry(entryName); try (InputStream in = srcArchive.getInputStream(entry)) {
if (entry != null) {
InputStream in = srcArchive.getInputStream(entry);
ZipOutputStream out = mapArchiveStreams.get(file); ZipOutputStream out = mapArchiveStreams.get(file);
out.putNextEntry(new ZipEntry(entryName)); out.putNextEntry(new ZipEntry(entryName));
InterpreterUtil.copyStream(in, out); InterpreterUtil.copyStream(in, out);
in.close();
} }
} }
finally {
srcArchive.close();
}
} }
catch (IOException ex) { catch (IOException ex) {
String message = "Cannot copy entry " + entryName + " from " + source + " to " + file; String message = "Cannot copy entry " + entryName + " from " + source + " to " + file;
@ -306,4 +288,4 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
DecompilerContext.getLogger().writeMessage("Cannot close " + file, IFernflowerLogger.Severity.WARN); DecompilerContext.getLogger().writeMessage("Cannot close " + file, IFernflowerLogger.Severity.WARN);
} }
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2014 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -78,13 +78,9 @@ public class ContextUnit {
String oldName = cl.qualifiedName; String oldName = cl.qualifiedName;
StructClass newCl; StructClass newCl;
DataInputFullStream in = loader.getClassStream(oldName); try (DataInputFullStream in = loader.getClassStream(oldName)) {
try {
newCl = new StructClass(in, cl.isOwn(), loader); newCl = new StructClass(in, cl.isOwn(), loader);
} }
finally {
in.close();
}
lstClasses.add(newCl); lstClasses.add(newCl);
@ -168,4 +164,4 @@ public class ContextUnit {
public List<StructClass> getClasses() { public List<StructClass> getClasses() {
return classes; return classes;
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2014 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -119,17 +119,11 @@ public class StructContext {
} }
if (filename.endsWith(".class")) { if (filename.endsWith(".class")) {
try { try (DataInputFullStream in = loader.getClassStream(file.getAbsolutePath(), null)) {
DataInputFullStream in = loader.getClassStream(file.getAbsolutePath(), null); StructClass cl = new StructClass(in, isOwn, loader);
try { classes.put(cl.qualifiedName, cl);
StructClass cl = new StructClass(in, isOwn, loader); unit.addClass(cl, filename);
classes.put(cl.qualifiedName, cl); loader.addClassLink(cl.qualifiedName, new LazyLoader.Link(LazyLoader.Link.CLASS, file.getAbsolutePath(), null));
unit.addClass(cl, filename);
loader.addClassLink(cl.qualifiedName, new LazyLoader.Link(LazyLoader.Link.CLASS, file.getAbsolutePath(), null));
}
finally {
in.close();
}
} }
catch (IOException ex) { catch (IOException ex) {
String message = "Corrupted class file: " + file; String message = "Corrupted class file: " + file;
@ -143,10 +137,8 @@ public class StructContext {
} }
private void addArchive(String path, File file, int type, boolean isOwn) throws IOException { private void addArchive(String path, File file, int type, boolean isOwn) throws IOException {
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed") //noinspection IOResourceOpenedButNotSafelyClosed
ZipFile archive = type == ContextUnit.TYPE_JAR ? new JarFile(file) : new ZipFile(file); try (ZipFile archive = type == ContextUnit.TYPE_JAR ? new JarFile(file) : new ZipFile(file)) {
try {
Enumeration<? extends ZipEntry> entries = archive.entries(); Enumeration<? extends ZipEntry> entries = archive.entries();
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement(); ZipEntry entry = entries.nextElement();
@ -178,12 +170,9 @@ public class StructContext {
} }
} }
} }
finally {
archive.close();
}
} }
public Map<String, StructClass> getClasses() { public Map<String, StructClass> getClasses() {
return classes; return classes;
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2014 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -73,15 +73,15 @@ public class StructMember {
protected StructGeneralAttribute readAttribute(DataInputFullStream in, ConstantPool pool, String name) throws IOException { protected StructGeneralAttribute readAttribute(DataInputFullStream in, ConstantPool pool, String name) throws IOException {
StructGeneralAttribute attribute = StructGeneralAttribute.createAttribute(name); StructGeneralAttribute attribute = StructGeneralAttribute.createAttribute(name);
int length = in.readInt();
if (attribute == null) { if (attribute == null) {
in.discard(in.readInt()); in.discard(length);
} }
else { else {
byte[] data = new byte[in.readInt()]; byte[] data = in.read(length);
in.readFull(data);
attribute.setInfo(data); attribute.setInfo(data);
attribute.initContent(pool); attribute.initContent(pool);
} }
return attribute; return attribute;
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2015 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -47,17 +47,13 @@ public class LazyLoader {
} }
public ConstantPool loadPool(String classname) { public ConstantPool loadPool(String classname) {
try { try (DataInputFullStream in = getClassStream(classname)) {
DataInputFullStream in = getClassStream(classname); if (in != null) {
if (in == null) return null;
try {
in.discard(8); in.discard(8);
return new ConstantPool(in); return new ConstantPool(in);
} }
finally {
in.close(); return null;
}
} }
catch (IOException ex) { catch (IOException ex) {
throw new RuntimeException(ex); throw new RuntimeException(ex);
@ -67,11 +63,8 @@ public class LazyLoader {
public byte[] loadBytecode(StructMethod mt, int codeFullLength) { public byte[] loadBytecode(StructMethod mt, int codeFullLength) {
String className = mt.getClassStruct().qualifiedName; String className = mt.getClassStruct().qualifiedName;
try { try (DataInputFullStream in = getClassStream(className)) {
DataInputFullStream in = getClassStream(className); if (in != null) {
if (in == null) return null;
try {
in.discard(8); in.discard(8);
ConstantPool pool = mt.getClassStruct().getPool(); ConstantPool pool = mt.getClassStruct().getPool();
@ -118,17 +111,13 @@ public class LazyLoader {
} }
in.discard(12); in.discard(12);
byte[] code = new byte[codeFullLength];
in.readFull(code); return in.read(codeFullLength);
return code;
} }
break; break;
} }
} }
finally {
in.close();
}
return null; return null;
} }
@ -170,4 +159,4 @@ public class LazyLoader {
this.internalPath = internalPath; this.internalPath = internalPath;
} }
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2014 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,36 +20,15 @@ import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
public class DataInputFullStream extends DataInputStream { public class DataInputFullStream extends DataInputStream {
public DataInputFullStream(byte[] bytes) { public DataInputFullStream(byte[] bytes) {
super(new ByteArrayInputStream(bytes)); super(new ByteArrayInputStream(bytes));
} }
public int readFull(byte[] b) throws IOException { public byte[] read(int n) throws IOException {
int length = b.length; return InterpreterUtil.readBytes(this, n);
byte[] temp = new byte[length];
int pos = 0;
int bytes_read;
while (true) {
bytes_read = read(temp, 0, length - pos);
if (bytes_read == -1) {
return -1;
}
System.arraycopy(temp, 0, b, pos, bytes_read);
pos += bytes_read;
if (pos == length) {
break;
}
}
return length;
} }
public void discard(int n) throws IOException { public void discard(int n) throws IOException {
if (super.skip(n) != n) { InterpreterUtil.discardBytes(this, n);
throw new IOException("Skip failed");
}
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2015 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,6 @@ import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import java.io.*; import java.io.*;
import java.nio.channels.FileChannel;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -31,27 +30,11 @@ public class InterpreterUtil {
public static final int[] EMPTY_INT_ARRAY = new int[0]; public static final int[] EMPTY_INT_ARRAY = new int[0];
private static final int CHANNEL_WINDOW_SIZE = IS_WINDOWS ? 64 * 1024 * 1024 - (32 * 1024) : 64 * 1024 * 1024; // magic number for Windows
private static final int BUFFER_SIZE = 16 * 1024; private static final int BUFFER_SIZE = 16 * 1024;
public static void copyFile(File in, File out) throws IOException { public static void copyFile(File source, File target) throws IOException {
FileInputStream inStream = new FileInputStream(in); try (FileInputStream in = new FileInputStream(source); FileOutputStream out = new FileOutputStream(target)) {
try { copyStream(in, out);
FileOutputStream outStream = new FileOutputStream(out);
try {
FileChannel inChannel = inStream.getChannel();
FileChannel outChannel = outStream.getChannel();
long size = inChannel.size(), position = 0;
while (position < size) {
position += inChannel.transferTo(position, CHANNEL_WINDOW_SIZE, outChannel);
}
}
finally {
outStream.close();
}
}
finally {
inStream.close();
} }
} }
@ -64,28 +47,35 @@ public class InterpreterUtil {
} }
public static byte[] getBytes(ZipFile archive, ZipEntry entry) throws IOException { public static byte[] getBytes(ZipFile archive, ZipEntry entry) throws IOException {
return readAndClose(archive.getInputStream(entry), (int)entry.getSize()); try (InputStream stream = archive.getInputStream(entry)) {
return readBytes(stream, (int)entry.getSize());
}
} }
public static byte[] getBytes(File file) throws IOException { public static byte[] getBytes(File file) throws IOException {
return readAndClose(new FileInputStream(file), (int)file.length()); try (FileInputStream stream = new FileInputStream(file)) {
return readBytes(stream, (int)file.length());
}
} }
private static byte[] readAndClose(InputStream stream, int length) throws IOException { public static byte[] readBytes(InputStream stream, int length) throws IOException {
try { byte[] bytes = new byte[length];
byte[] bytes = new byte[length];
int n = 0, off = 0; int n = 0, off = 0;
while (n < length) { while (n < length) {
int count = stream.read(bytes, off + n, length - n); int count = stream.read(bytes, off + n, length - n);
if (count < 0) { if (count < 0) {
throw new IOException("premature end of stream"); throw new IOException("premature end of stream");
}
n += count;
} }
return bytes; n += count;
} }
finally {
stream.close(); return bytes;
}
public static void discardBytes(InputStream stream, int length) throws IOException {
if (stream.skip(length) != length) {
throw new IOException("premature end of stream");
} }
} }
@ -159,4 +149,4 @@ public class InterpreterUtil {
public static String makeUniqueKey(String name, String descriptor1, String descriptor2) { public static String makeUniqueKey(String name, String descriptor1, String descriptor2) {
return name + ' ' + descriptor1 + ' ' + descriptor2; return name + ' ' + descriptor1 + ' ' + descriptor2;
} }
} }

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2015 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -69,26 +69,18 @@ public class BulkDecompilationTest {
} }
private static void unpack(File archive, File targetDir) { private static void unpack(File archive, File targetDir) {
try { try (ZipFile zip = new ZipFile(archive)) {
ZipFile zip = new ZipFile(archive); Enumeration<? extends ZipEntry> entries = zip.entries();
try { while (entries.hasMoreElements()) {
Enumeration<? extends ZipEntry> entries = zip.entries(); ZipEntry entry = entries.nextElement();
while (entries.hasMoreElements()) { if (!entry.isDirectory()) {
ZipEntry entry = entries.nextElement(); File file = new File(targetDir, entry.getName());
if (!entry.isDirectory()) { assertTrue(file.getParentFile().mkdirs() || file.getParentFile().isDirectory());
File file = new File(targetDir, entry.getName()); try (InputStream in = zip.getInputStream(entry); OutputStream out = new FileOutputStream(file)) {
assertTrue(file.getParentFile().mkdirs() || file.getParentFile().isDirectory());
InputStream in = zip.getInputStream(entry);
OutputStream out = new FileOutputStream(file);
InterpreterUtil.copyStream(in, out); InterpreterUtil.copyStream(in, out);
out.close();
in.close();
} }
} }
} }
finally {
zip.close();
}
} }
catch (IOException e) { catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

Loading…
Cancel
Save