Sunday, July 19, 2015

Effective Java item 45: Minimize the scope of local variables

Summary of the item 45.

1. Declare a local variable where it is first used.
(Instance variables declaration should be at the top of the class. from Clean Code by Robert C. Martin, page 80)

2. Nearly every local variable declaration should contain an initializer.

3. Prefer for loops to while loops

4. Keep methods small and focused.

Those are very basic rules of clean code.







Friday, July 17, 2015

Effective Java item 6: Eliminate obsolete object references

In Effective Java book, item 6, there is a source code that causes memory leak.

I tested the code to see if it really causes critical memory leak, and here is the result




The source code from the book that causes memory leak.

public class Stack {
    private Object[] elements;
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 1;
    
    public Stack() {
        elements = new Object[DEFAULT_INITIAL_CAPACITY];
    }
    
    public void push(Object e) {
        ensureCapacity();
        elements[size++]=e;
    }
    
    public Object pop(){
        if(size==0){
            throw new EmptyStackException();
        }
         
        return elements[--size];
    }

    private void ensureCapacity() {
        if(elements.length == size) 
            elements = Arrays.copyOf(elements, 2*size + 1);
    }
}

The part that causes memory leak is pop() method.

When the stack grows and then shrinks, the stack still holds the obsolete object references.

To avoid that, we need to null out the obsolete objects.

Here is the modified code of pop() method.

public Object pop(){
    if(size==0){
        throw new EmptyStackException();
    }
    
    Object obj = elements[--size];
    elements[size] = null;
    return obj;
}


Let's test if the original code really causes memory leak, and the modified one solves the problem.

Here is the code that I used to test. First test uses the original Stack class that causes memory leak.

public class TestApplication {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        
        long startTime = System.currentTimeMillis();
           
        Stack stack = new Stack();
        
        for(int j=0; j<10000000; j++) {
            stack.push(new Object());
        }
        
        for(int j=0; j<10000000; j++) {
            stack.pop();
        }

        // Get the Java runtime
        Runtime runtime = Runtime.getRuntime();
        // Run the garbage collector
        runtime.gc();
        // Calculate the used memory
        long memory = runtime.totalMemory() - runtime.freeMemory();
        System.out.println("Used memory is bytes: " + memory);
        System.out.println("Used memory is megabytes: "
            + bytesToMegabytes(memory));
       
        
        long stopTime = System.currentTimeMillis();
        long elapsedTime = stopTime - startTime;
        System.out.println("elapsed Time is: " + elapsedTime);
        
            
    }
    
    private static final long MEGABYTE = 1024L * 1024L;

    public static long bytesToMegabytes(long bytes) {
      return bytes / MEGABYTE;
    }

}
Result is
Used memory is bytes: 227572000
Used memory is megabytes: 217
elapsed Time is: 5279
Now modify the Stack class so that no memory leak created, and the Result is
Used memory is bytes: 67572000
Used memory is megabytes: 64
elapsed Time is: 3724


Clearly, the pop() method had memory leak problem, and by null out the obsolete object, it is solved

Done

I quit AGC and landed a job as a full time programmer



I quit AGC and landed a job as a full time programmer.

Good Bye Glass Industry! It was fun to work as a simulation engineer, but programming is much more fun to me.


Now, I develop native android application, and I'm much more happy now =D


Wednesday, July 3, 2013

How to add scroll bar to your JScrollPane

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author Lee
 */

public class MyTableFrame extends JPanel {
    
    
    
    public MyTableFrame() {
        Object[][] data = {
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
            {null, null, null, null, null, null, null, null, null, null, null, null, null, null, null},
        };

        String[] columnNames = new String[data[0].length];
        for(int i=0; i<data[0].length; i++) {
            columnNames[i] = "column: " + i;
        }
            
        DefaultTableModel myModel = new DefaultTableModel(data, columnNames);
        JTable myTable = new JTable(myModel);
        
        // Here, we add vertial scroll bar and horizontal scroll bar
        // VERTICAL_SCROLLBAR_ALWAYS could be VERTIAL_SCROLLBAR_AS_NEEDED 
        // same for horizontal bar
        JScrollPane myScrollPane = new JScrollPane(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        myTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        myScrollPane.getViewport().add(myTable);
        
        this.add(myScrollPane);
    }
    
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("SimpleTableDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        //Create and set up the content pane.
        MyTableFrame newContentPane = new MyTableFrame();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);
 
        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }
 
    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
    
};