I have got a Java memory puzzle from internet and trying hard to understand it, and what I understood till now is that Java is releasing memory of object with ended life on initialization of new object, though I am unable to get any proof on the same. If any one have any idea on it please guide.
Puzzle is as below
private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);
public void f()
{
{
byte[] data = new byte[dataSize];
}
//int i = 0; //If uncommented then program work fine
byte[] data2 = new byte[dataSize];
}
Related
I want to create a renderscript in android where an array is passed to the .rs file. On these values some calculation is done and sent back to the user.
I have very little understanding of renderscript, so what I have written might be completely wrong also. Please help me with it.
Android activity
public class RenderTemp extends Activity {
private RenderScript mRS;
private ScriptC_snow mScript;
int[] indices;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.render);
indices = new int[2];
indices[0] = 1;
indices[1] = 2;
createScript();
}
private void createScript() {
mRS = RenderScript.create(this);
Allocation mIN = Allocation.createSized(mRS, Element.I32(mRS), indices.length);
mIN.copyFrom(indices);
mScript = new ScriptC_snow(mRS);
mScript.forEach_root(mIN);
mIN.copyTo(indices);
}
}
snow.rs
#pragma version(1)
#pragma rs java_package_name(#package name)
int32_t *mIN;
void __attribute__((kernel)) root(int32_t in)
{
in = in + 2;
}
Modifying "in" inside your kernel won't cause anything to get updated. You can change it such that your root() function has a return value of int32_t as well. Then do "return in + 2;". Finally, you can pass mIN for both input and output to the forEach (so "mScript.forEach_root(mIn, mIn);"). Even though this will work for you, I would strongly advocate that you separate the input and output Allocations for any real work, as aliasing input/output like this can prevent compiler optimizations for more complex code.
I'm having bad times with creating typical card/deck class in java. I've read some similar questions & answers but either they're not relatable/helpful or I can't simply comprehend it yet.
Here's the code
public class Cards {
boolean isAvailable;
int card_id;
static final int AC = 32;
public Cards [] deck = new Cards[AC];
public void set () {
int a = 0;
for (int i = 0; i < AC; i++) {
if(a == 4) a = 0;
deck[i].isAvailable = true; // <---------
deck[i].card_id = i + (a * 101); // <---------
a++;
}
}
public void read () {
for (int i = 0; i < AC; i++)
System.out.println(deck[i].isAvailable + " " + deck[i].card_id);
}
public static void main (String[] args) {
Cards c = new Cards();
c.set();
c.read();
}
}
Exception in thread "main" java.lang.NullPointerException
at Cards.set(Cards.java:13)
at Cards.main(Cards.java:24)
1.
I've read about similar issues and found that problem can be in initialization of an array and I've tried to do the same with my prog but it went bad anyway.
I marked 13th and 14th lines because they are being pointed (when i comment 13th line just for check, pointer sets to the next line).
2.
Next part of help I would like to get from you is:
Even though there is main (for training purposes), I see other class using this class (which just creates deck) so I guess I won't be needing main... Is everything well set besides probs in first point?
Very simple:
public Cards [] deck = new Cards[AC];
creates an empty array with AC number of slots for Cards objects.
Now you have to put a non-null Cards object into each slot!
But thing is: actually your abstraction is broken.
You wrote code that seems to take one card to be the same as a card set - by adding that array of Cards into your Cards class! And that makes it actually hard to fix your current code. As the "normal" way to fix this would be to add a constructor like
public Cards() {
deck = new Cards[AC];
for (int i=0; i<deck.length;i++) {
deck[i] = new Cards();
}
If you try that ... you immediately run into an endless recursion (creating one new Cards would result in creating AC new Cards (to fill the array); causing a stackoverflow very soon.
Thus the real answer goes somewhere along these lines:
public class Card {
... a class that represents a SINGLE card in your game
and then
public card GameOfCards {
... a class that (for example!) uses an array to hold n objects of class Card!
Finally, as Peter is indicating in his comment: you should learn to use debugging means to work on such problems yourself. One good way: before using any data structure, iterate it and print out its content. Or even better, learn how to use a debugger, and walk through your code step by step! As you should please understand: this is very basic stuff; that you normally should not bring forward here.
I am working on a project for school and things are going well until i tried to perform a merge sort on my ArrayList.
It will run but then it errors out. The first error of many is Exception in thread "main" java.lang.StackOverflowError.
I have looked over the code and cant find out why the error is occurring.
It does give me a location ( line 74:first_half = mergeSort(first_half); ) but i don't see the issue.
public static void main(String[] args) throws IOException {
// URL url = new
// URL("https://www.cs.uoregon.edu/Classes/15F/cis212/assignments/phonebook.txt");
FileReader fileReader = new FileReader("TestSort.txt");
BufferedReader bufferReader = new BufferedReader(fileReader);
String entry = bufferReader.readLine();
// Scanner s = new Scanner(url.openStream());
// int count = 0;
while (entry != null) {
// String person = s.nextLine();
String phoneNum = entry.substring(0, 7);
String name = entry.substring(9);
PhonebookEntry newentry = new PhonebookEntry(name, phoneNum);
phoneBook.add(newentry);
entry = bufferReader.readLine();
}
// ********************Selection
// Sort*************************************
ArrayList<PhonebookEntry> sortList = new ArrayList<PhonebookEntry>(phoneBook);
for (int min = 0; min < sortList.size(); min++) {
for (int i = min; i < sortList.size(); i++) {
int res = sortList.get(min).getName().compareTo(sortList.get(i).getName());
if (res > 0) {
PhonebookEntry temp = sortList.get(i);
sortList.set(i, sortList.get(min));
sortList.set(min, temp);
}
}
}
for (PhonebookEntry sortentry : sortList) {
System.out.println(sortentry);
}
System.out.println(mergeSort(mergeSortList));
}
// *****************************merge sort******************************************
static int mergecounter = 0;
static ArrayList<PhonebookEntry> mergeSortList = new ArrayList<PhonebookEntry>(appMain.phoneBook);
public static ArrayList<PhonebookEntry> mergeSort(ArrayList<PhonebookEntry> mergeSortLists) {
if (mergeSortLists.size() == 1) {
return mergeSortLists;
}
int firstHalf = mergeSortLists.size() % 2 == 0 ? mergeSortLists.size() / 2 : mergeSortLists.size() / 2 + 1;
ArrayList<PhonebookEntry> first_half = new ArrayList<PhonebookEntry>(mergeSortLists.subList(0, firstHalf));
ArrayList<PhonebookEntry> mergeSortHalf2 = new ArrayList<PhonebookEntry>(
mergeSortLists.subList(first_half.size(), mergeSortLists.size()));
System.out.println(++mergecounter);
first_half = mergeSort(first_half);
mergeSortHalf2 = mergeSort(mergeSortHalf2);
return merge(first_half, mergeSortHalf2);
}
public static ArrayList<PhonebookEntry> merge(ArrayList<PhonebookEntry> first_half,
ArrayList<PhonebookEntry> mergeSortHalf2) {
ArrayList<PhonebookEntry> returnMerge = new ArrayList<PhonebookEntry>();
while (first_half.size() > 0 && mergeSortHalf2.size() > 0) {
if (first_half.get(0).getName().compareTo(mergeSortHalf2.get(0).getName()) > 0) {
returnMerge.add(mergeSortHalf2.get(0));
mergeSortHalf2.remove(0);
}
else {
returnMerge.add(first_half.get(0));
first_half.remove(first_half.get(0));
}
}
while (first_half.size() > 0) {
returnMerge.add(first_half.get(0));
first_half.remove(first_half.get(0));
}
while (mergeSortHalf2.size() > 0) {
returnMerge.add(mergeSortHalf2.get(0));
mergeSortHalf2.remove(mergeSortHalf2.get(0));
}
return returnMerge;
}
}
My opinion there is no error in code.
How so sure?
I ran you code in my environment and its executed without any error.
With the text file i found at https://www.cs.uoregon.edu/Classes/15F/cis212/assignments/phonebook.txt As input
and done a simple implementation for PhonebookEntry
Then why is this error?
First off all try to understand the error, I mean why StackOverflowError occur. As there are lots of I am not going to explain this
But please read the top answer of this two thread and i am sure you will know why this happen.
Thread 1: What is a StackOverflowError?
Thread 2: What actually causes a Stack Overflow error?
If you read those I hope you understand the summury is You Ran Out Of Memory.
Then why I didnt got that error: Possible reason is
In my environment I configured the jvm to run with a higher memory 1024m to 1556m (as eclipse parameter)
Now lets analyze your case with solution:
Input: you have big input here ( 50,000 )
To check you code try to shorten the input and test.
You have executed two algorithm in a sigle method over this big Input:
When a method execute all its varibles stay in the memory untill it complete its execution.
so when you are calling merge sort all previouly user vairables and others stay in the memory which can contribute to this situation
Now if you use separated method and call them from the main method like write an method for selection sort, all its used varible will go out of scope
and possibly be free (if GC collect them) after the selection sort is over.
So write two separated method for reading input file and selection sort.
And Please Please close() those FileReader and BufferedReader.
Get out of those static mehtod . Make them non static create and object of the class and call them from main method
So its all about code optimization
And also you can just increase the memory for jvm and test by doing like this java -Xmx1556m -Xms1024m when ruining the app in command line
BTW, Thanks for asking this this question its gives me something to think about
I have been looking at this for a while. First off, here is some code:
MyActivity.java:
MeasurementType type = handler.getMeasurementType(DEFAULT_TYPE);
ArrayList<Unit> unitsConverted = new ArrayList<Unit>();
unitsConverted.addAll(Arrays.asList(type.getUnits()));
DataBaseHandler.java:
public MeasurementType getMeasurementType(String measurementType) {
SQLiteDatabase db = this.getReadableDatabase();
int num = getMeasurementUnitCount(measurementType);
MeasurementType mType = MeasurementType.getMeasurementType(measurementType);
Unit[] units = new Unit[num];
String getUnits = "SELECT unit_name, view FROM " + measurementType;
Cursor cursor = db.rawQuery(getUnits, null);
for(int i = 0; i <= units.length-1; i++) {
if(cursor.moveToNext()) {
Unit u = new Unit();
u.setUnitName(cursor.getString(0));
u.setView(cursor.getInt(1));
units[i] = u;
}
}
mType.setUnits(units);
return mType;
}
I am not quite sure why this is happening but after this line:
mType.setUnits(units)
The debugger is telling me that the property is null...
num is 21 which is right, the array units goes from 0 to 20, which is right.
Here is my implementation of the setUnits(units) method in my MeasurementType class:
protected void setUnits(Unit[] passedUnits) {
units = new Unit[passedUnits.length+1];
System.arraycopy(passedUnits, 0, units, 0, passedUnits.length);
}
it works ok too...
in fact when the method getMeasurement is finished and I am back in my activity, it still says null.
However stepping through to creating the ArrayList and then doing:
unitsConverted.addAll(Arrays.asList(type.getUnits()));
works fine...the ArrayList is populated fine. But one thing that I don't understand is why the debugger is telling me that the property is null...it has been happening to this specific circumstance for some time now, I haven't been able to fix it.
Further information you might need to know is that MeasurementType is an abstract class that instantiates a subclass based on a string that is passed to it, so it definitely creates a subclass and intialises everything :)
In a project of mine I constantly compress little blocks of data.
Now I find out that the jvm then grows to 6GB of ram (resident (RES) RAM, not shared or virtual or so) and then die because of out of memory.
It is as if the garbage collector never runs or so.
I've pulled out the relevant code and pasted it below. When I run it (java6, 32 bit linux) it grows to 1GB of ram.
Anyone got an idea how to reduce the memory usage?
import java.util.Random;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
class test {
int blockSize = 4096;
Random r = new Random();
public test() throws Exception {
blockSize = 4096;
byte [] data = new byte[blockSize];
for(int index=0; index<blockSize; index++)
data[index] = (byte)r.nextInt();
for(long cnt=0; cnt<1000000; cnt++) {
byte [] result = compress(data);
if (result != null)
data[0] = result[0];
}
}
byte [] compress(byte [] in) {
assert in.length == blockSize;
Deflater compresser = new Deflater();
compresser.setInput(in);
compresser.finish();
byte [] out = new byte[in.length];
int outLen = compresser.deflate(out);
if (outLen < blockSize) {
byte [] finalOut = new byte[outLen];
System.arraycopy(out, 0, finalOut, 0, outLen);
return finalOut;
}
return null;
}
public static void main(String [] args) throws Exception {
new test();
}
}
Well, Folkert van Heusden solved his own problem, but to summarize:
Early in the compress(byte [] in)-method, we create a java.util.zip.Deflater.
We use the Deflater to do some stuff, and then we leave the compress()-method. We loose our reference to the deflater-variable. At this point, the Deflater is no longer in use, and is waiting to be killed by the garbage collector.
Deflater allocates both Java heap memory and C/C++/native heap memory. The native heap memory that are allocated by a Deflater, will be held until Deflater.finalize-method is called by the garbage collector. If the garbage collector doesn't run fast enough (there might be plenty free java heap memory), we can run out of C/C++ heap memory. If this happen, we will get "Out of memory"-errors.
The Oracle bug report JDK-4797189 is probably related. It contains a code snippet that illustrates and reproduces the problem:
public class Bug {
public static void main( String args[] ) {
while ( true ) {
/* If ANY of these two lines is not commented, the JVM
runs out of memory */
final Deflater deflater = new Deflater( 9, true );
final Inflater inflater = new Inflater( true );
}
}
}
The solution is to free the resources when you are finished by calling the Deflater.end()-method (or Inflater.end()).
Well, It seems to me that there is no memory leak in the code, so it actually seems the VM is not GC-ing byte arrays.
"Anyone got an idea how to reduce the memory usage?"
Well, I would try with
byte firstByteOfDataWhichIsCompressedAndThenUncompressed(byte [] in) { ... }
which specifically returns the first byte of the uncompressed array, rather than the whole array. I know, it's a horrible method name, and I hope you will find a better one.
The following code
for(long cnt=0; cnt<1000000; cnt++) {
byte [] result = compress(data);
if (result != null)
data[0] = result[0];
}
would become
for(long cnt=0; cnt<1000000; cnt++)
data[0] = firstByteOfDataWhichIsCompressedAndThenUncompressed(data);