I read some material about Java memory leak. It implements FIFO Queue with array to semantically leak memory. But I don't understand why it will cause memory leak. Is it because it didn't nullify the unused slot in the 'pop' operation? Anyone can explain to me?
queue[head] = null
The FIFO Queue implementation is as follows:
public class FIFOQueue {
private Object[] queue;
private int size = 0, head = 0, tail = 0;
private static final int INITIAL_CAPACITY = 16;
public FIFOQueue() {
queue = new Object[INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
queue[tail] = e;
size++;
tail = increment(tail);
}
public Object pop() throws EmptyStackException {
if (size == 0)
throw new EmptyStackException();
size–;
Object returnValue = queue[head];
head = increment(head);
return returnValue;
}
/** doubling the capacity each time the array needs to grow. */
private void ensureCapacity() {
if (queue.length == size)
queue = Arrays.copyOf(queue, 2 * size + 1);
}
/** make sure the pointers are wrapped around at the end of the array */
private int increment( int x ) {
if( ++x == queue.length )
x = 0;
return x;
}
}
You answered your own Question:)
Since you don't clean queue reference Garbage Collector, can't clean it from memory, because you have valid reference to this Object in your FIFOQueue. That way you pollute your memory with unused Objects, reducing memory effectively available to your program.
Also as pointed in comments, your ensureCapasity function will only work, when the tail is at the end of an array, otherwise you'll be loosing elements in your queue on push, this is more critical then queue[head] reference problem.
Related
I am looking at a part of code that is used for an IDA* search. When a node is expanded, its child states are then put into the StateCache datastructure, which is a stack as far as I can tell. My question is this: is there any reason one would choose to set the max size of an array to a particular value? The cache data member has a number of elements equal to 10*1024, which seems to me that the cache data member is supposed to only store up to 10 KB (?) of elements, but I am really not sure. What would be the justification for the10*1024 number? Note that I have found this and this stack overflow posts that discuss cache hit/miss w.r.t row-major vs. column-major access of arrays, but these don't answer my question. Also, this code had no comments, otherwise I would've included more.
public class StateCache {
public static final int MAX_CACHE_SIZE = 10 * 1024;
int size;
State[] cache;
public StateCache() {
size = 0;
cache = new State[MAX_CACHE_SIZE];
}
// push and pop operations
public State get(State original) {
if (size > 0) {
size--;
State result = cache[size];
result.init(original);
return result;
} else {
return new State(original);
}
}
public void put(State[] children) {
for (State child: children) {
if (child == null) {
return;
}
if (size >= MAX_CACHE_SIZE) {
return;
}
cache[size] = child;
size++;
}
}
}
I need to implement something with a heap sort, and I am having a bug with it.
In the Heap class:
private serial[] data;
private int size;
private static final int FRONT = 1;
public Heap(){
serial[] data = new serial[1000]; //serial - object with a String
this.size = 0;
data[0] = new serial("");
}
public void insert(serial t){
size++;
data[size] = t; **<--- Null Pointer EXCEPTION**
int current = size;
while(data[current].serialNumber() > data[parent(current)].serialNumber()){
swap(parent(current), current);
current = parent(current);
}
}
(and more functions of course for the heap implementation).
and the main class:
public class Simulation {
public static void main(String[] args) {
Heap maxHeap = new Heap();
maxHeap.insert(new serial("a"));
maxHeap.insert(new serial("ba"));
maxHeap.print();
}
}
(I insert Strings and return a sorted array based on numbers)
I ran the program, and it returns a Null Pointer Exception (to the insert function, it is written in the code where).
for some reason, it says that: (in the Heap class)
private serial[] data;
was never used.
In the heap constructor I initialized the instance variable again.
Thanks to Seelenvirtuose
My queue uses a stack hence I have two stacks.. s1 that accepts the add, then all of its items get moved into s2 which makes s2 my queue.
(no use of arrays..)
here is my implementation but when I test it, my remove unit test fails.
public class Queue
{
private Stack s1;
private Stack s2;
private int size;
public Queue()
{
//arbitrary sized.
s1 = new Stack();
s2 = new Stack();
size = 0;
}
public void insert(Object o)
{
//add object into s1.
s1.push(o);
size++;
}
//delete from queue
public Object remove()
{
int n = 0; ... arbitrary size n. //size not specified
for(int i = 1; i <= n ; i++)
{
//push all elements in s1 into s2
s2.insert(s1.pop());
}
//decrease the size
size--;
return s2.pop;
}
public Object peekFront()
{
s2.push(s1.pop());
return s2.peek();
}
}
TEST
import org.junit.Assert;
import static org.junit.Assert.*;
import org.junit.Test;
public class QueueTest
{
protected Queue q;
public QueueTest()
{
q = new Queue();
}
atTest
public void testRemove()
{
assertTrue(q.isEmpty()); -- passes
q.insert(10);
q.insert(11);
q.insert(12);
q.insert(23);
//remove
assertEquals(10, q.remove()); --- fails
}
public void testPeekFront()
{
q.insert(80);
q.insert(90);
q.insert(57);
assertEquals(20,q.peekFront());
}
}
Please can you put me in the right direction on why my public Object remove is not functioning correctly...
For example when I try to remove 23? My test passes but when I test for 10 which actually should be, then it fails.
Here is the complete code..... for both the class and the test...
I think you may be providing a static value for n. As the value n , will change dynamically, please make sure you are giving n=s1.size() [or any custom function to calculate size]. Please provide the complete code.
Assumed Fixes:
1. You are popping out all elements from s1 , during remove. Making it(s1) empty stack. So you have to fill it back by popping the values from s2 in the remove function itself. As fabian mentioned in the next answer use a helper method for transfering of elements from 1 stack to another.
2.In remove() method, store s1.pop() to a temp variable and remove all elements in s2. return temp variable. Other wise s2 will keep on growing.
3. set n = s1.size();
4. return s1.pop();
For the method to work you cannot simply hardcode the size. Furthermore you have to move the elements back to the original stack before the next insertion, or the order becomes wrong. I recommend transfering the objects in a helper method to avoid code duplication:
private static void transfer(Stack source, Stack target) {
while (!source.isEmpty()) {
target.push(source.pop());
}
}
I recommend moving the elements lazily to avoid unnecessary operations for repeated insert or repeated remove operations:
public void insert(Object o) {
// lazily transfer values back
transfer(s2, s1);
//add object into s1.
s1.push(o);
size++;
}
//delete from queue
public Object remove() {
if (s1.isEmpty() && s2.isEmpty()) {
return null; // alternative: throw exception
}
transfer(s1, s2);
//decrease the size
size--;
return s2.pop();
}
public Object peekFront() {
if (s1.isEmpty() && s2.isEmpty()) {
return null; // alternative: throw exception
}
transfer(s1, s2);
return s2.peek();
}
Alternatively you could simply transfer the values back to s1 in the remove method, which would make it a bit simpler to implement additional operations, however it would also make some operation sequences less efficient. (You also still need to fix peekFront()):
//delete from queue
public Object remove() {
if (s1.isEmpty() && s2.isEmpty()) {
return null; // alternative: throw exception
}
transfer(s1, s2);
//decrease the size
size--;
Object result = s2.pop();
transfer(s2, s1);
return result;
}
How can we achieve Circular buffer implementation in Android?
Is there a way we can re-use a pre-defined method if exists? or do we have support for C standard libraries in Android?
In Android development first preference is to use Java rather than C for implementing these things. Ofcourse you can do that in C (using JNI) but that requires certain overheads i.e. you need to implement your own garbage collection logic along with the code of circular buffer whereas in Java this can be achieved automatically. . See below class if it works for your case..
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
public class CustomCircularBuffer<T> {
private T[] buffer;
private int tail;
private int head;
public CustomCircularBuffer(int n) {
buffer = (T[]) new Object[n];
tail = 0;
head = 0;
}
public void add(T toAdd) {
if (head != (tail - 1)) {
buffer[head++] = toAdd;
} else {
throw new BufferOverflowException();
}
head = head % buffer.length;
}
public T get() {
T t = null;
int adjTail = tail > head ? tail - buffer.length : tail;
if (adjTail < head) {
t = (T) buffer[tail++];
tail = tail % buffer.length;
} else {
throw new BufferUnderflowException();
}
return t;
}
public String toString() {
return "CustomCircularBuffer(size=" + buffer.length + ", head=" + head + ", tail=" + tail + ")";
}
}
Here are some other useful links which can give necessary explanations ..
Example
Another Example
In Depth Article
I just realized that ArrayDeque would be a good implementation for this.
There is also CircularArray from Android support.
CircularArray is a generic circular array data structure that provides
O(1) random read, O(1) prepend and O(1) append. The CircularArray
automatically grows its capacity when number of added items is over
its capacity.
I can't tell its performance, but from a quick glance at the Javadocs, it seems to be designed with efficiency in mind. Not so sure anymore.
Say I have the following Stack class (taken from Joshua Bloch's Effective Java):
import java.util.Arrays;
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size];
}
/**
* Ensure space for at least one more element, roughly doubling the capacity
* each time the array needs to grow.
*/
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
My question is about the ensureCapacity method and the Arrays.copyOf JDK method: how can we be positive that the old elements array object can be garbage collected since copyOf seems to be creating a new array object?
In other words, if a new object is created each time ensureCapacity is called, where do the old objects go and is there no risk of a memory leak?
The "old objects" (the elements in the array) get copied into the new array in this line:
elements = Arrays.copyOf(elements, 2 * size + 1);
As for the old elements array, it'll eventually get garbage collected, because there are no more references pointing to it.