am 03af0c42: Merge "Ensure that RandomAccessFile is not leaked." into lmp-dev

* commit '03af0c42d80734c44198b96a99488bb94816ae97':
  Ensure that RandomAccessFile is not leaked.
This commit is contained in:
Deepanshu Gupta
2014-12-03 20:58:27 +00:00
committed by Android Git Automerger
2 changed files with 34 additions and 38 deletions

View File

@@ -16,74 +16,61 @@
package com.android.layoutlib.bridge.libcore.io; package com.android.layoutlib.bridge.libcore.io;
import java.nio.MappedByteBuffer; import java.nio.ByteBuffer;
import libcore.io.BufferIterator; import libcore.io.BufferIterator;
/** /**
* Provides an implementation of {@link BufferIterator} over a {@link MappedByteBuffer}. * Provides an implementation of {@link BufferIterator} over a {@link ByteBuffer}.
*/ */
public class BridgeBufferIterator extends BufferIterator { public class BridgeBufferIterator extends BufferIterator {
private int mPosition;
private final long mSize; private final long mSize;
private final MappedByteBuffer mMappedByteBuffer; private final ByteBuffer mByteBuffer;
public BridgeBufferIterator(long size, MappedByteBuffer buffer) { public BridgeBufferIterator(long size, ByteBuffer buffer) {
mSize = size; mSize = size;
mMappedByteBuffer = buffer; mByteBuffer = buffer;
} }
@Override @Override
public void seek(int offset) { public void seek(int offset) {
assert offset < mSize; assert offset <= mSize;
mPosition = offset; mByteBuffer.position(offset);
} }
@Override @Override
public void skip(int byteCount) { public void skip(int byteCount) {
assert mPosition + byteCount <= mSize; int newPosition = mByteBuffer.position() + byteCount;
mPosition += byteCount; assert newPosition <= mSize;
mByteBuffer.position(newPosition);
} }
@Override @Override
public void readByteArray(byte[] dst, int dstOffset, int byteCount) { public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
assert dst.length >= dstOffset + byteCount; assert dst.length >= dstOffset + byteCount;
mMappedByteBuffer.position(mPosition); mByteBuffer.get(dst, dstOffset, byteCount);
mMappedByteBuffer.get(dst, dstOffset, byteCount);
mPosition = mMappedByteBuffer.position();
} }
@Override @Override
public byte readByte() { public byte readByte() {
mMappedByteBuffer.position(mPosition); return mByteBuffer.get();
byte b = mMappedByteBuffer.get();
mPosition = mMappedByteBuffer.position();
return b;
} }
@Override @Override
public int readInt() { public int readInt() {
mMappedByteBuffer.position(mPosition); return mByteBuffer.getInt();
int i = mMappedByteBuffer.getInt();
mPosition = mMappedByteBuffer.position();
return i;
} }
@Override @Override
public void readIntArray(int[] dst, int dstOffset, int intCount) { public void readIntArray(int[] dst, int dstOffset, int intCount) {
mMappedByteBuffer.position(mPosition);
while (--intCount >= 0) { while (--intCount >= 0) {
dst[dstOffset++] = mMappedByteBuffer.getInt(); dst[dstOffset++] = mByteBuffer.getInt();
} }
mPosition = mMappedByteBuffer.position();
} }
@Override @Override
public short readShort() { public short readShort() {
mMappedByteBuffer.position(mPosition); return mByteBuffer.getShort();
short s = mMappedByteBuffer.getShort();
mPosition = mMappedByteBuffer.position();
return s;
} }
} }

View File

@@ -25,6 +25,7 @@ import android.system.ErrnoException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.nio.ByteOrder;
import java.nio.MappedByteBuffer; import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode; import java.nio.channels.FileChannel.MapMode;
import java.util.HashMap; import java.util.HashMap;
@@ -59,15 +60,22 @@ public class MemoryMappedFile_Delegate {
} }
path = path.substring(TARGET_PATH.length()); path = path.substring(TARGET_PATH.length());
try { try {
RandomAccessFile file = new RandomAccessFile(new File(sRootPath, path), "r"); File f = new File(sRootPath, path);
long size = file.length(); if (!f.exists()) {
MemoryMappedFile_Delegate newDelegate = new MemoryMappedFile_Delegate(file); throw new ErrnoException("File not found: " + f.getPath(), 1);
long filePointer = file.getFilePointer(); }
MemoryMappedFile mmFile = new MemoryMappedFile(filePointer, size); RandomAccessFile file = new RandomAccessFile(f, "r");
long delegateIndex = sManager.addNewDelegate(newDelegate); try {
sMemoryMappedFileMap.put(mmFile, delegateIndex); long size = file.length();
file.close(); // Also closes the channel opened by the delegate constructor. MemoryMappedFile_Delegate newDelegate = new MemoryMappedFile_Delegate(file);
return mmFile; long filePointer = file.getFilePointer();
MemoryMappedFile mmFile = new MemoryMappedFile(filePointer, size);
long delegateIndex = sManager.addNewDelegate(newDelegate);
sMemoryMappedFileMap.put(mmFile, delegateIndex);
return mmFile;
} finally {
file.close();
}
} catch (IOException e) { } catch (IOException e) {
throw new ErrnoException("mmapRO", 1, e); throw new ErrnoException("mmapRO", 1, e);
} }
@@ -85,7 +93,7 @@ public class MemoryMappedFile_Delegate {
@LayoutlibDelegate @LayoutlibDelegate
static BufferIterator bigEndianIterator(MemoryMappedFile file) { static BufferIterator bigEndianIterator(MemoryMappedFile file) {
MemoryMappedFile_Delegate delegate = getDelegate(file); MemoryMappedFile_Delegate delegate = getDelegate(file);
return new BridgeBufferIterator(delegate.mSize, delegate.mMappedByteBuffer); return new BridgeBufferIterator(delegate.mSize, delegate.mMappedByteBuffer.duplicate());
} }
// TODO: implement littleEndianIterator() // TODO: implement littleEndianIterator()
@@ -95,6 +103,7 @@ public class MemoryMappedFile_Delegate {
// It's weird that map() takes size as long, but returns MappedByteBuffer which uses an int // It's weird that map() takes size as long, but returns MappedByteBuffer which uses an int
// to store the marker to the position. // to store the marker to the position.
mMappedByteBuffer = file.getChannel().map(MapMode.READ_ONLY, 0, mSize); mMappedByteBuffer = file.getChannel().map(MapMode.READ_ONLY, 0, mSize);
assert mMappedByteBuffer.order() == ByteOrder.BIG_ENDIAN;
} }
public static void setDataDir(File path) { public static void setDataDir(File path) {