Trying to allocate (direct memory) with Javolution.Struct that contains arrays, and the memory "explodes". No idea why, Would love to have a clue
Class A holds array of 50 of class B. Class B holds array of 1 million unsigned shorts:
import javolution.io.Struct;
public class Test {
public static void main(String[] args) {
Test t = new Test();
t.work();
}
public void work() {
A a = new A();
System.out.println("a.size() = "+a.size()); // prints 100000000
}
}
public class A extends Struct {
public B[] randomName = array(new B[50]);
}
public class B extends Struct {
public Unsigned16[] someData = array(new Unsigned16[1000000]);
}
The reason I need those arrays in one piece is the comfort of calling getByteBuffer() and getting the whole structure as single piece of memory, directly allocated in non jvm memory
The memory shows (10 GB) 6 GB instead of 100MB
no clue why
[ javolution 6.1.0 ]
Edit 1:
A more concise issue found to cause the same memory problem:
public Unsigned16[] someData = array(new Unsigned16[50000000]);
Allocating 50m unsigned16 in main (class needs to extend Struct obv) function is expected to have a 100mb memory footprint where its actually allocates 6gb
Edit 2:
Its not happening if i'm calling the same line, without the wrapping with array() function:
public Unsigned16[] someData = new Unsigned16[50000000];
This is weird. I need the struct to contain this array, along with other Struct members (like Signed8 etc..), and when calling getByteBuffer() it will have the same piece of memory allocated and not pointers to different structs
Edit 3:
This works as expected:
ByteBuffer bb = ByteBuffer.allocateDirect(100*1000000); // allocates 100MB
I suspect there is a bug in Struct.array function in javolution lib. I will keep this post open until its fixed or someone post a workaround..
Related
I am getting a bit confused regarding few points regarding Java memory management.
Understood what is the difference between Stacks and Heap and I went to see a proper example on what is those memories when we execute some code.
I took for example this few lines
public static void main(String[] args)
{
int a = 5;
calculate(a);
System.out.println(a); //will print 5 not 50
}
private static void calculatee(int a)
{
a = a * 10;
}
I understood what is happening in the stack and in the heap. The variable is not getting returned and there is no reference to the Heap in this case.
while in this example:
public static void maina(String[] args)
{
Customer customer = new Customer("John");
setAName(customer);
System.out.println(customer.getName()); // this will return Philip
}
private static void setAName(Customer c)
{
c.setName("Philip");
}
I can see the state of the object changed this time!
Stacks are not shared thought threads, but heap is shared! Which make sense to me that the object customer has changed its value from Jhon to Philip when I am printing it!
Great! all make sense!
However, I was expecting that if I will do this
public static void main(String[] args)
{
Integer i = new Integer(5);
calculate(i);
System.out.println(i); // printing 5 and not 50
}
private static void calculate(Integer i)
{
i = i * 10;
}
I would get 50 and not 5!
In this case Integer is an object and I am assuming it is created in the heap!
Funny thing is that if I will wrap the Integer inside Customer I will get 50 instead of 5.
Why is this happening? Isn't the Integer type getting created in the Heap?
This is a problem of references and not of heaps and stacks.
When calling the method calculate, you pass a reference (in your case, i from main).
The trick is, that Java will create a new reference inside of calculate. So i inside of calculate and i inside of main might initially "point" to the same object, but they are not the "same".
So, if you change i inside of calculate to the object resulting from your multiplication, you don't automatically change the reference of the i inside of main.
With Customer, it's different. You never change where c in setAName points to. You change one reference inside of the object, but both customer inside of main and c in setAName still point to that one object!
Here two shitty Paint drawings to explain what I mean (numbers prefixed with 0x are references):
For the Integer example:
For the Customer example:
Don't hesitate to come back with any questions.
I hope this helps.
In the below program, does it mean that 3 instance variables and 3 instance methods are created and memory is allocated to them ?
class Foo{
String name = "";
public void greet(String name){
this.name = name;
}
}
class Greetings {
public static void main (String[] args) {
Foo ob = new Foo();
Foo ob1 = new Foo();
Foo ob2 = new Foo();
ob.greet("hello friends");
ob1.greet("welcome to java");
ob2.greet("let us learn");
System.out.println(ob.name);
System.out.println(ob1.name);
System.out.println(ob2.name);
}
}
The Java Language Specification does not say anything about how memory is organized, or how objects, methods, and classes are represented.
So, the answer is: you can't and shouldn't know.
All the 3 objects are stored in a heap memory. The size of the heap increases decreases as the application runs. The new operator here allocates memory to the object in the heap. Which means each time you say new in the statement a separate memory space is allocated to that object in the heap The methods are stored in JVM internal heap.
you can find a simple example of how memory is managed for objects in java here
When we make calls like below :-
class Class{
int x;
public Class(int a){
x = a;
}
public void display(){
System.out.println(x);
}
}
And in main method, then we use the class' object to display data :-
new Class(5).display(); // object 1
new Class(7).display(); // object 2
Now, my question is :-
Whether what I've represented from object 1 and object 2 will be equal or
distinct(in terms of memory locations in heap)? Whether two separate
memory locations will be created in heap(dynamic memory allocator) OR
whether the same object(memory location in heap) will be used?
I am having this confusion since a long time. Also I am merely a noob in Java.
Please elaborate with respect to the heap section/dynamic memory allocation to Class object using new call.
When you create two objects with new operator they will look for you as different objects in the heap. So if you compare then with == they won't much. However if your code is JIT-compiled, heap allocation will not occur at all as JIT-compiler is smart enough to inline the constructor and display() method and conclude that it can be just rewritten to
System.out.println(5);
System.out.println(7);
But if you actually compare them with ==, then probably this optimization will be turned off and two distinct objects will be allocated on the heap.
It will be Two distict objects in the heap,every time you use the new operator
public class Test {
int x;
public Test(int a){
x = a;
}
public void display(){
System.out.println(x);
}
public static void main(String args[]){
Test firstInstance = new Test(5);
Test secondInstance = new Test(5);
if(firstInstance == secondInstance)
System.out.println("same");
else
{
System.out.println("firstInstance"+firstInstance);
System.out.println("secondInstance"+secondInstance);
}
}
}
When I'm using jna, both GlobalAlloc And GlobalLock returns Pointer, but I found both of them performing as if they are not equal.
For example,
On this case below, I found instance of TestStructure is
not in proper state which I expected.
Kernel32 kernel32 = Native.loadLibrary("kernel32",Kernel32.class);
Pointer pointer = kernel32.GlobalAlloc(ghnd, size);
Pointer pointer2 = kernel32.GlobalLock(pointer);
pointer2.write(0, testbyte, 0, dmSize);
TestStructure structure = new TestStructure(pointer);
but the case below working fine.
Kernel32 kernel32 = Native.loadLibrary("kernel32",Kernel32.class);
Pointer pointer = kernel32.GlobalAlloc(ghnd, size);
Pointer pointer2 = kernel32.GlobalLock(pointer);
pointer2.write(0, testbyte, 0, dmSize);
TestStructure structure = new TestStructure(pointer2);
Why do I have to use pointer2 instance to create TestStructure.
I think both pointer and pointer2 should points same place.
//add 2015.04.03
1 Yes, I'm working on Windows Platform.
2 See below for TestStrucure.
public class TestStructure extends Structure {
public char[] dmDeviceName = new char[32];
public WORD dmSpecVersion;
public WORD dmDriverVersion;
public WORD dmSize;
public WORD dmDriverExtra;
public DWORD dmFields;
public UnionField1 unionField1;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
public char[] dmFormname = new char[32];
public WORD dmLogPixels;
public DWORD dmBitsPerpel;
public DWORD dmPelsWidth;
public DWORD dmPelsHeight;
public UnionField2 unionField2;
public DWORD dmDisplayFrequency;
public TestStructure(Pointer pointer) {
useMemory(pointer);
read();
}
#Override
protected List getFieldOrder() {
return Arrays.asList(new String[] { "dmDeviceName", "dmSpecVersion", "dmDriverVersion", "dmSize",
"dmDriverExtra", "dmFields", "unionField1", "dmColor", "dmDuplex", "dmYResolution", "dmTTOption",
"dmCollate", "dmFormname", "dmLogPixels", "dmBitsPerpel", "dmPelsWidth", "dmPelsHeight", "unionField2",
"dmDisplayFrequency" });
}
}
I assume you are working on a Windows platform. The GlobalXx functions are in fact a reminiscence of old 16 bits Windows. In that (old) time, GlobalAlloc used to return a (16 bits) handle that was converter to a 32 bits pointer by GlobalLock.
You can still exhibit similar behaviour if you ask for a movable memory block, by using GHND = 0x42 as first parameter. If you do GlobalAlloc returns a (32 bits) handle that must be converted into a true pointer with GlobalLock. The memory block can be assigned different pointer values across different calls to GlobalLock - GlobalUnlock.
The page in MSDN states Note The global functions have greater overhead and provide fewer features than other memory management functions. New applications should use the heap functions unless documentation states that a global function should be used. That means that MicroSoft advices to use HeapAlloc serie functions instead, unless you are required to use GlobalAlloc.
References from the MSDN :
GlobalAlloc function
Comparing Memory Allocation Methods
So let's say:
public class Sample { //main() class
public static void main(String[] args) {
A a = new A();
}
}
public class A {
A aa = new A();
}
So...when I run it ...it gives : java.lang.StackOverflowError.
So, my explanation is that object a generation at line 1, furthers creates object aa generation at line 2...and then it enters a recursion .... which keeps creating object after object, until the heap memory is full.
If the objects are created on Heap...then why does it say StackOverflowError ??
Well, it's using both heap and stack. The stack space is because you're in the constructor for A, recursively. It would be simpler to see this if you put the initialization in the body of the constructor:
public class A {
A aa;
public A() {
aa = new A();
}
}
So the A constructor calls itself, then calls itself, etc. There's generally rather more heap space available than stack space, hence why you're running out of stack space first. If your class had a lot of fields, you would conceivably run out of heap space first - although usually the heap is pretty huge in modern machines.
The reason for a stack overflow is simply that the stack runs out of space before the (small) As can fill up the heap.
You have correctly recognized the recursion. So!