From C to Java: an introduction to Java for C programmers

(Continued from our introduction to Java for C programmers.)

Memory management

When it comes to memory management, C often puts the onus on the programmer. For any "long-lived" structure (by which we essentially mean one that exists across independent function calls), it is generally up to the programmer to (a) call some memory management function such as malloc() to allocate memory for it and, crucially, (b) call a complementary function such as free() to deallocate the memory once it is no longer needed. That implies that the programmer must determine when the structure is no longer required, which in a complex application can be an extremely arduous task. A common type of bug is a memory leak, in which the programmer "forgets" to de-allocate objects when they are no longer needed.

In Java, memory management is handled by the Java Virtual Machine (in effect, by the "Java system"). The programmer creates objects or of a given class, but the JVM takes care of actually allocating memory for that object from its heap. The JVM also takes care of garbage collection: that is, de-allocating memory for objects that are no longer referenced. Automatic garbage collection alleviates the likelihood of memory leaks to some extent (although does not protect against the problem where references to an object are held on to accidentally when they're not needed).

A subtle and related point is that Java objects are always passed by reference. In C, if we execute a statement such as:

struct Object obj;
doSomething(obj);
...
void doSomething(Object obj) {
  // only affects the copy!
  obj.field = x;
}

the structure obj is passed by value. That is, a copy is made of the struct and placed on the stack. Inside the doSomething() method, when we assign the value x to obj, we're actually affecting the copy. To get round this, we can pass a pointer:

struct Object *obj;
doSomething(obj);
...
void doSomething(Object *obj) {
  // affects the original object
  obj->field = x;
}

Semantically, Java objects are always passed by pointer, although strictly speaking they are passed by reference. The difference is that a reference to an object isn't (necessarily) literally the memory address of the object. And it can't be used for any other purpose other than to access the fields of that particular object.

This brings us neatly on to our next section: pointers vs references.


If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.

Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.