8010697: DeletedArrayFilter seems to leak memory

Reviewed-by: hannesw, sundar
This commit is contained in:
James Laskey 2013-06-19 09:10:49 -03:00 committed by Jim Laskey
parent 93241c0ecb
commit d643a2fcd7
9 changed files with 133 additions and 3 deletions

View File

@ -856,8 +856,12 @@ public final class NativeArray extends ScriptObject {
}
// delete missing elements - which are at the end of sorted array
sobj.setArray(array.delete(sorted.length, len - 1));
}
if (sorted.length != len) {
array = array.delete(sorted.length, len - 1);
}
sobj.setArray(array);
}
return sobj;
} catch (final ClassCastException | NullPointerException e) {

View File

@ -294,6 +294,29 @@ public abstract class ArrayData {
*/
public abstract ArrayData set(int index, double value, boolean strict);
/**
* Set an empty value at a given index. Should only affect Object array.
*
* @param index the index
* @return new array data (or same)
*/
public ArrayData setEmpty(final int index) {
// Do nothing.
return this;
}
/**
* Set an empty value for a given range. Should only affect Object array.
*
* @param lo range low end
* @param hi range high end
* @return new array data (or same)
*/
public ArrayData setEmpty(final long lo, final long hi) {
// Do nothing.
return this;
}
/**
* Get an int value from a given index
*

View File

@ -128,6 +128,18 @@ abstract class ArrayFilter extends ArrayData {
return this;
}
@Override
public ArrayData setEmpty(final int index) {
underlying.setEmpty(index);
return this;
}
@Override
public ArrayData setEmpty(final long lo, final long hi) {
underlying.setEmpty(lo, hi);
return this;
}
@Override
public int getInt(final int index) {
return underlying.getInt(index);

View File

@ -142,6 +142,7 @@ final class DeletedArrayFilter extends ArrayFilter {
final long longIndex = ArrayIndex.toLongIndex(index);
assert longIndex >= 0 && longIndex < length();
deleted.set(longIndex);
underlying.setEmpty(index);
return this;
}
@ -149,6 +150,7 @@ final class DeletedArrayFilter extends ArrayFilter {
public ArrayData delete(final long fromIndex, final long toIndex) {
assert fromIndex >= 0 && fromIndex <= toIndex && toIndex < length();
deleted.setRange(fromIndex, toIndex + 1);
underlying.setEmpty(fromIndex, toIndex);
return this;
}

View File

@ -202,6 +202,8 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
@Override
public ArrayData delete(final int index) {
final long longIndex = ArrayIndex.toLongIndex(index);
underlying.setEmpty(index);
if (longIndex + 1 == lo) {
lo = longIndex;
} else if (longIndex - 1 == hi) {
@ -220,6 +222,7 @@ final class DeletedRangeArrayFilter extends ArrayFilter {
}
lo = Math.min(fromIndex, lo);
hi = Math.max(toIndex, hi);
underlying.setEmpty(lo, hi);
return this;
}

View File

@ -138,6 +138,18 @@ final class ObjectArrayData extends ArrayData {
return this;
}
@Override
public ArrayData setEmpty(final int index) {
array[index] = ScriptRuntime.EMPTY;
return this;
}
@Override
public ArrayData setEmpty(final long lo, final long hi) {
Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi, (long)Integer.MAX_VALUE), ScriptRuntime.EMPTY);
return this;
}
@Override
public int getInt(final int index) {
return JSType.toInt32(array[index]);
@ -165,11 +177,13 @@ final class ObjectArrayData extends ArrayData {
@Override
public ArrayData delete(final int index) {
setEmpty(index);
return new DeletedRangeArrayFilter(this, index, index);
}
@Override
public ArrayData delete(final long fromIndex, final long toIndex) {
setEmpty(fromIndex, toIndex);
return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
}
@ -181,7 +195,7 @@ final class ObjectArrayData extends ArrayData {
final int newLength = (int) (length() - 1);
final Object elem = array[newLength];
array[newLength] = 0;
setEmpty(newLength);
setLength(newLength);
return elem;
}

View File

@ -203,6 +203,18 @@ class SparseArrayData extends ArrayData {
return this;
}
@Override
public ArrayData setEmpty(final int index) {
underlying.setEmpty(index);
return this;
}
@Override
public ArrayData setEmpty(final long lo, final long hi) {
underlying.setEmpty(lo, hi);
return this;
}
@Override
public int getInt(final int index) {
if (index >= 0 && index < maxDenseLength) {

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JDK-8010697: DeletedArrayFilter seems to leak memory
*
* @test
* @run
*/
var N = 1000;
var array = new Array(N);
var WeakReferenceArray = Java.type("java.lang.ref.WeakReference[]");
var refArray = new WeakReferenceArray(N);
for (var i = 0; i < N; i ++) {
var object = new java.lang.Object();
array[i] = object;
refArray[i] = new java.lang.ref.WeakReference(object);
}
object = null;
for (var i = 0; i < N; i ++) {
delete array[i];
}
java.lang.System.gc();
java.lang.System.gc();
for (var i = 0; i < N; i ++) {
if (refArray[i].get() != null) {
print("Reference found at " + i);
exit(0);
}
}
print("All references gone");

View File

@ -0,0 +1 @@
All references gone