Re: Java Memory question
On 14/03/11 15:04, Eric wrote:
On Mar 14, 10:34 am, Joshua Cranmer <Pidgeo...@verizon.invalid> wrote:
On 03/14/2011 10:10 AM, Eric wrote:
If I create a native object like
byte[] myData = new byte[byteSize];
then I fill it with data,
how do I release the memory?
Do I just null it?
myData = null;
All objects [1] in Java are garbage collected, so the memory will be
freed when the last reference to an object is lost. You can of course
have references to an object as variables within the scope, elements of
an Object array, or as objects in a class [2]. If it's a local variable,
the reference will be lost when leaving the scope within which it is
defined (i.e., pair of curly braces); you can lose the reference earlier
by explicitly nullifying it.
To move it to a new object using as little memory as possible do I
just null each?
byte[] myNewData = new byte[byteSize];
for (int byteLoop = 0; byteLoop< byteSize; byteLoop ++) {
myNewData[byteLoop] = myData[byteLoop];
myData[byteLoop] = null;
}
Or is there a better way to move it without eating double memory?
Judging by the code you're trying to write, byte[] myNewData = myData;
would probably be more than sufficient, since that gives the new data a
reference to the same memory to begin with, and it doesn't involve
copying the array again. If you need a subarray of only a portion of the
data, java.util.Arrays.copyOf might work better for you.
[1] Well, primitives aren't, but they aren't exactly objects to begin with.
[2] Or they can be rooted by the JVM while being used by native APIs,
but I digress.
--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth
The point of copying the array is that I can't create the new object
as a reference to the same memory, because the copy is a cloned object
on a different machine through a webstart.
I don't know what you mean by this. But your client cannot have direct
access to memory on the server. If the client has received an object
from the server then it is actually an object in the client, regardless
that it's been copied from the server.
Correct me if I'm wrong.
If I actually knew what you meant I might, but I may have misunderstood
what you meant.
1. It appears a client object and a server object in a webstart
session affect the same memory limit in a webstart.
What do you mean by a webstart session? A client can only ever access
memory in the client. Any data objects which are sent from the server to
the client are copies of whatever exists on the server, and take up
memory allocation within the client.
2. It should use a lot less memory if I create an empty (large) array
object on the client then copy and destroy the array elements of the
server object one at a time.
If it's an array of primitives you cannot destroy part of it, it is one
object, a single entity in the heap. If it's an array of references then
null'ing the source array would have no effect unless you are actually
creating a new object which is a copy/clone of the old object. If you
merely copy the reference from the source array to the destination array
then null'ing the reference in the source array will achieve nothing
whatsoever. The new array would contain a reference to the original
object, so it won't get GC'd.
3. It is more efficient to declare variables global (to the class
object) rather than local (to the method) if the method may be called
more than once.
Beware your terminology. You are straying into very mistaken wording.
There is no such thing as a "global" variable within an object, or
within Java. There are 3 types of variables in Java.
Class variables.
These belong to the class. There is one copy of any such variable and
it's shared between all objects of that class.
Instance variables.
These belong to an object, and each object has its own copy.
Local variables.
These are local to a method.
Instance variables exist from the time they are created (when the object
is created) until the object of which they are a part is destroyed. An
instance variable may refer many different objects over its lifetime.
Local variables are allocated on the stack and automatically go out of
scope when the method returns. An object which is only referenced by a
local variable (within the method) will be free to be GC'd when the
method returns. But any such object is not GC'd by the action of the
method returning, it only become available for GC at some later time.
4. Variables must be global if their value must persist between
methods.
Again, they are not "global". They are just not local to a method. They
will most likely be instance variables and accessible by any instance
methods. Their value will be part of the object, not just a method. They
are not global because they won't be accessible to any other object
(unless declared public, and the other object has a reference to the
object, or the object provides an accessor method).
5. Variables are implicitly set to release memory at the method end
(return/throw) if they're declared within the method. Explicitly
setting them to null would get no benefit.
Variables, yes. Objects, maybe. Just because a local variable goes out
of scope when a method returns does not imply that an object to which it
referred is free to be GC'd. But, yes, setting them to null is pointless.
6. Variables must be explicitly cleared (object = null) to release
memory at a method end if they're declared as global.
Not global. If you mean they are instance variables, then why would you
do that anyway? If the variable, and the object to which it refers,
should only exist within the method then make it a local variable. Then
allocate a new instance of the object within the method. Java will take
care of the GC for you. I can't see any point in declaring an instance
variable, allocating a new object to that instance variable in a method,
then null'ing the instance variable before the method returns. Also,
null'ing an instance variable won't release an object for GC if there is
still a reference to that object elsewhere.
7. Declaring and creating a large object within a method which may be
called more than once which is only used by that method may take
longer to execute than declaring it globally and creating it once, but
will free up memory when the method is not being called.
Maybe, maybe not. The object will be free for GC when the method
returns, but it may not get GC'd when the the method returns.
But it may save time in the GC if that large object is never available
for GC.
Am I missing anything? Any particular tips to avoiding the
OutOfMemory exception other than increasing the initial memory
allocation?
I think you are missing the distinction between a variable (reference),
and the instance of a class (object) to which it refers.
--
Nigel Wade