Java Memory Management

by HSG on Aug 28, 2012 in Java Tutorial

I will begin our blog on Java Tutorial with an incredibly important aspect of java development:  memory management.  The importance of this topic should not be minimized as an application's performance and footprint size are at stake.

From the outset, the Java Virtual Machine (JVM) manages memory via a mechanism known as Garbage Collection (GC).  The Garbage collector

  • Manages the heap memory.   All obects are stored on the heap; therefore, all objects are managed.  The keyword, new, allocates the requisite memory to instantiate an object and places the newly allocated memory on the heap.  This object is marked as live until it is no longer being reference.
  • Deallocates or reclaims those objects that are no longer being referened. 
  • Traditionally, employs a Mark and Sweep algorithm.  In the mark phase, the collector identifies which objects are still alive.  The sweep phase identifies objects that are no longer alive.
  • Deallocates the memory of objects that are not marked as live.
  • Is automatically run by the JVM and not explicitely called by the Java developer.  Unlike languages such as C++, the Java developer has no explict control over memory management.
  • Does not manage the stack.  Local primitive types and local object references are not managed by the GC.

So if the Java developer has no control over memory management, why even worry about the GC?  It turns out that memory management is an integral part of an application's performance, all things being equal.  The more memory that is required for the application to run, the greater the likelihood that computational efficiency suffers. To that end, the developer has to take into account the amount of memory being allocated when writing code.  This translates into the amount of heap memory being consumed.

Memory is split into two types:  stack and heap.  Stack memory is memory set aside for a thread of execution e.g. a function.  When a function is called, a block of memory is reserved for those variables local to the function, provided that they are either a type of Java primitive or an object reference.  Upon runtime completion of the function call, the reserved memory block is now available for the next thread of execution.  Heap memory, on the otherhand, is dynamically allocated.  That is, there is no set pattern for allocating or deallocating this memory.  Therefore, keeping track or managing this type of memory is a complicated process. In Java, such memory is allocated when instantiating an object:

String s = new String();  // new operator being employed
String m = "A String";    /* object instantiated by the JVM and then being set to a value.  The JVM
calls the new operator */

In the String example above, a String object is being created in both cases and placed on the heap.  In the first case, we employ the new operator to instantiate the String; in the second case, this call is made by the JVM behind the scenes.


The process of instantiating an object is quite expensive and occurs via the following steps:

  1. Heap memory is allocated.
  2. Instance fields are set to their default values.
  3. Initialization blocks are called.
  4. The object's constructor is called.
  5. The object's super constructor is called.
  6. Superclass instance fields are given specified values.
  7. The body of the super class constructor is called.
  8. ... repeat necessary steps above fall all super classes.

Obviously, instantiating an object or acquiring heap memory can a very costly process.  So how do we minimize this cost?  Below are some examples of how to minimize and application's heap dependency.


Keep Object Instantiation to a Minimum

Work with primitives instead of objects.

int k = 0; // places an int, declared locally, on the stack
Integer K = new Integer(k); //places an Integer object on the heap a comparatively costly process.

/* Be careful of autoboxing.  In the method below, having an object 
as a parameter will automatically convert a primitive type to an object */

public class MemoryExample { 

    public void someMethod(Object o){ ... }

    public static void main(String[] args){

       MemoryExample me = new MemoryExample(): 
       int m = 4; 
       me.someMethod(m); //converts m to an Integer 

     }

    /* consider creating someMethod() as follows: public void someMethod(int i) { ... }
       this will avoid autoboxing altogether since the primitive int will not force the JVM to 
       instantiate an object. */ 
}

Create classes that do not need to be instantiated.

When reading the documentation on the Java Math class, you should notice that all of the member variables and methods are class fields and class methods respectively.  This means that the developer does not have to instantiate a Math object whenever making a computation.  Just think of the object overhead or memory footprint if the application were to do one to two thousand computations per minute.  Also, notice that the Math class excepts primitives so boxing is not a concern.  If this were not to be the case, then memory requirements would be compounded by the creation of wrapper objects such as Integer, Decimal and the like.

To create your own class that uses static methods, declare methods and fields to be static.

public class EmployeeSalaryComp{
      public final static double annualBonusPercentage = 4.2531;
      public static double employeeRaise(double salary){
              return salary * (annualBonusPercentage/100);
      }      
}

//when invoking EmployeeSalaryComp, an object does not need to be created
...
EmployeeSalaryComp.employeeRaise(johns_salary);

Avoid String Concatenation

Be careful not to use the string concatenation (+) operator when working with strings and use StringBuilder or StringBuffer instead.  Every time you concatenate a String, you are creating another object.  This is due to the fact that strings are immutable and therefore force the contenation operator to create a new String that is the contenation of two other strings.  StringBuilder and StringBuffer, on the other hand, will append one String to anther and not create a new String.

String s = new String("Java Training");
   s += " is great";
/*The String concatenation operation above will result in the creation of an additional 
String*/

   StringBuffer sb = new StingBuffer("Java Training");
   sb.append(" is great");

// or

   StringBuilder sbuild = new StringBuilder("Java Training");
   sbuild.append(" is great."):

/* StringBuilder was added in Java 5.0 to provide a non-synchronized version of StringBuffer and is, 
therefore, the preferred way to concatenate strings when thread saftey is not a concern as it is 
faster than StringBuffer. */

 

Set Unused Object References to null

Although we cannot explicitly manage memory, we can help the GC work more efficiently.  Take a look at the example below. 

//C++ example
Object a = new Object();
delete a;

//Java example
Object a = new Object();
a = null;

In C++, memory management is achieved explicity by use of the delete operator.  Although Java has no equivalent, setting references to objects that are no longer needed will aid the garbage collector to reclaim the memory to which they refer.


Instantiate a Singleton or Work with Object Pools

Wherever possible, reuse objects that have already been created.  The Spring Framework delivers on that promise as should you.  Create only one object of a certain type and pass it around to various execution threads to be used over and over again.  Use object pools as well, in particular, when  working with database connection objects.  If the JVM had to create a database call for each sql query, think of all the overhead that is incurred.

Stack and Heap in Java - a Clarification

As is shown in the example below, all instantiated objects are placed on the heap.  This includes the value of their primitive members as well.  In MemoryExample,  intmember is placed on the heap.    The reference objectmember is also placed on the heap as is the object to which it refers.  As for local variables, i.e. those declared within the method of a class, primitive types and object references are placed on the stack. The objects to which these local references refer, however, are placed on the heap.

public class MemoryExample{

private int intmember = 2;  //reference stored on heap with the MemoryExample reference.
private Object objectmember = new Object(); 
// a is a reference to a literal object that has been placed on the heap.

public void someMethod(){
   int localprimitive = 4; // placed on the stack because it refers to a java primitive type
   Object localobject = new Object();  /* references an object placed on the heap eventhough the 
variable is declared as a variable local to the method, someMethod().  The reference, localobject, 
is placed on the stack. */
}}

other blog entries

Is a period of free consulting an effective way to acquire new businesswith a potential client?
As a Software Developer, How Can You Increase Your Earning Potential?
Python, a Zen Poem
Danger In The Middle: Why Mid-Level Managers Are not Ready To Lead?
Why the McDonald's Approach to Computer Learning Doesn't Work
Is Apple Worth the Price?
The importance of exercise for IT professionals
Google Email and Scanning Scam
Programming in F#: Unlock New Possibilities
JAVA SCRIPT TUTORIAL - THE ESSENTIAL ELEMENTS

Course Directory [training on all levels]

Upcoming Classes
Gain insight and ideas from students with different perspectives and experiences.

Interesting Reads Take a class with us and receive a book of your choosing for 50% off MSRP.

did you know? HSG is one of the foremost training companies in the United States

Information Technology Training that enables companies to build better applications and expertly manage the software development process.

Our courses focus on two areas: the most current and critical object-oriented and component based tools, technologies and languages; and the fundamentals of effective development methodology. Our programs are designed to deliver technology essentials while improving development staff productivity.

Personalized courses for unique business and technology needs

An experienced trainer and faculty member will identify the client's individual training requirements, then adapt and tailor the course appropriately. Our custom training solutions reduce time, risk and cost while keeping development teams motivated. The Hartmann Software Group's faculty consists of veteran software engineers, some of whom currently teach at several Colorado Universities. Our faculty's wealth of knowledge combined with their continued real world consulting experience enables us to produce more effective training programs to ensure our clients receive the highest quality and most relevant instruction available. Instruction is available at client locations or at various training facilities located in the metropolitan Denver area.

Upcoming Classes

consulting services we do what we know ... write software

Design and Development
Application lifecycle management
We generate use cases, UML documentation, architect the system, create an object model, iteratively develop the system, unit and system test and modularize where necessary. These types of engagements are typically longterm and, almost always, incorporate a variety of software technologies.
If you are in need of expertise but only require the assistance of one or two engineers, the Hartmann Software Group can be of help. Instead of procuring talent by way of a placement agency who is likely to contact us, come to the Hartmann Software Group directly. You may realize some savings.
Mentor
The best way to learn is by doing.

The coaching program integrates our course instruction with hands on software development practices. By employing XP (Extreme Programming) techniques, we teach students as follows:

Configure and integrate the needed development tools

MOntitor each students progress and offer feedback, perspective and alternatives when needed.

Establish an Action plan to yield a set of deliverables in order to guarantee productive learning.

Establish an Commit to a deliverable time line.

Hold each student accountable to a standard that is comparable to that of an engineer/project manager with at least one year's experience in the field.

These coaching cycles typically last 2-4 weeks in duration.

Provide Expertise
Services for your business growth.
With the introduction of smart devices, e-marketplaces, electronic forms, SEO practices, big data, virtual office environments, media streaming and so much more, there is hardly a business whose livelihood is not, in some way, dependent upon the inclusion of such software functionality into its online presence, work environment and product offerings. Such inclusion often presents a complex array of challenges that are far beyond the expertise of the business as it demands an understanding of technological options, modular decomposition, backend systems integration and web services. Most importantly, the business requires IT talent and expertise; this is where the Hartmann Software Group shines. To that end, here is an overview of some of the services that we offer:

Business Rule isolation and integration for large scale systems using Blaze Advisor

Develop Java, .NET, Perl, Python, TCL and C++ related technologies for Web, Telephony, Transactional i.e. financial and a variety of other considerations.

Windows and Unix/Linux System Administration.

Application Server Administration, in particular, Weblogic, Oracle and JBoss.

Desperate application communication by way of Web Services (SOAP & Restful), RMI, EJBs, Sockets, HTTP, FTP and a number of other protocols.

Graphics Rich application development work i.e. fat clients and/or Web Clients to include graphic design

Performance improvement through code rewrites, code interpreter enhancements, inline and native code compilations and system alterations.

Mentoring of IT and Business Teams for quick and guaranteed expertise transfer.

Architect both small and large software development systems to include: Data Dictionaries, UML Diagrams, Software & Systems Selections and more