try to unmap files when done
This commit is contained in:
@@ -198,6 +198,7 @@ class DownloadSession {
|
||||
|
||||
mapped.clear()
|
||||
digest.update(mapped)
|
||||
DataUtil.tryUnmap(mapped)
|
||||
byte [] hash = digest.digest()
|
||||
byte [] expected = new byte[32]
|
||||
System.arraycopy(infoHash.getHashList(), piece * 32, expected, 0, 32)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.muwire.core.files
|
||||
|
||||
import com.muwire.core.InfoHash
|
||||
import com.muwire.core.util.DataUtil
|
||||
|
||||
import net.i2p.data.Base64
|
||||
|
||||
@@ -59,6 +60,7 @@ class FileHasher {
|
||||
for (int i = 0; i < numPieces - 1; i++) {
|
||||
buf = raf.getChannel().map(MapMode.READ_ONLY, ((long)size) * i, size)
|
||||
digest.update buf
|
||||
DataUtil.tryUnmap(buf)
|
||||
output.write(digest.digest(), 0, 32)
|
||||
}
|
||||
def lastPieceLength = length - (numPieces - 1) * ((long)size)
|
||||
|
||||
@@ -56,7 +56,7 @@ class ContentUploader extends Uploader {
|
||||
writeMesh(request.downloader)
|
||||
os.write("\r\n".getBytes(StandardCharsets.US_ASCII))
|
||||
|
||||
FileChannel channel
|
||||
FileChannel channel = null
|
||||
try {
|
||||
channel = Files.newByteChannel(file.toPath(), EnumSet.of(StandardOpenOption.READ))
|
||||
mapped = channel.map(FileChannel.MapMode.READ_ONLY, range.start, range.end - range.start + 1)
|
||||
@@ -72,6 +72,10 @@ class ContentUploader extends Uploader {
|
||||
} finally {
|
||||
try {channel?.close() } catch (IOException ignored) {}
|
||||
endpoint.getOutputStream().flush()
|
||||
synchronized(this) {
|
||||
DataUtil.tryUnmap(mapped)
|
||||
mapped = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.muwire.core.util
|
||||
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
import com.muwire.core.Constants
|
||||
@@ -115,4 +118,39 @@ class DataUtil {
|
||||
e = e.getCause()
|
||||
e
|
||||
}
|
||||
|
||||
public static void tryUnmap(ByteBuffer cb) {
|
||||
if (cb==null || !cb.isDirect()) return;
|
||||
// we could use this type cast and call functions without reflection code,
|
||||
// but static import from sun.* package is risky for non-SUN virtual machine.
|
||||
//try { ((sun.nio.ch.DirectBuffer)cb).cleaner().clean(); } catch (Exception ex) { }
|
||||
|
||||
// JavaSpecVer: 1.6, 1.7, 1.8, 9, 10
|
||||
boolean isOldJDK = System.getProperty("java.specification.version","99").startsWith("1.");
|
||||
try {
|
||||
if (isOldJDK) {
|
||||
Method cleaner = cb.getClass().getMethod("cleaner");
|
||||
cleaner.setAccessible(true);
|
||||
Method clean = Class.forName("sun.misc.Cleaner").getMethod("clean");
|
||||
clean.setAccessible(true);
|
||||
clean.invoke(cleaner.invoke(cb));
|
||||
} else {
|
||||
Class unsafeClass;
|
||||
try {
|
||||
unsafeClass = Class.forName("sun.misc.Unsafe");
|
||||
} catch(Exception ex) {
|
||||
// jdk.internal.misc.Unsafe doesn't yet have an invokeCleaner() method,
|
||||
// but that method should be added if sun.misc.Unsafe is removed.
|
||||
unsafeClass = Class.forName("jdk.internal.misc.Unsafe");
|
||||
}
|
||||
Method clean = unsafeClass.getMethod("invokeCleaner", ByteBuffer.class);
|
||||
clean.setAccessible(true);
|
||||
Field theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
||||
theUnsafeField.setAccessible(true);
|
||||
Object theUnsafe = theUnsafeField.get(null);
|
||||
clean.invoke(theUnsafe, cb);
|
||||
}
|
||||
} catch(Exception ex) { }
|
||||
cb = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user