Thursday, 14 December 2017

ResultSet Interface in Java-JDBC

In the post Java JDBC Steps to Connect to DB we have already seen a complete example using the interfaces Driver, Connection, Statement and ResultSet provided by the JDBC API.

In this post we’ll see ResultSet interface in detail.

ResultSet interface

ResultSet interface resides in java.sql package and it represents the storage for the data you get by executing a SQL statement that queries the database.

A ResultSet object maintains a cursor pointing at the result data. Initially the cursor is positioned before the first row. The next method moves the cursor to the next row, it returns false when there are no more rows in the ResultSet object.

Example code – Creating and iterating a ResultSet

ResultSet rs = stmt.executeQuery("Select * from Employee");
   
// Processing Resultset
while(rs.next()){
 System.out.println("id : " + rs.getInt("id") + " Name : " +  rs.getString("name") + " Age : " + rs.getInt("age")); 
}

By default, ResultSet object is not updatable and has a forward moving cursor only. Thus, you can iterate through it only once and only from the first row to the last row. But ResultSet interface provides parameters that can produce ResultSet objects that are scrollable and/or updatable.

Fields for scrollable ResultSet

ResultSet interface has fields that determine whether ResultSet object will be scrollable or not and will it be sensitive to the changes to the data that is represented by ResultSet or not.

  • TYPE_FORWARD_ONLY - The constant indicating the type for a ResultSet object whose cursor may move only forward.
  • TYPE_SCROLL_INSENSITIVE - The constant indicating the type for a ResultSet object that is scrollable but generally not sensitive to changes to the data that underlies the ResultSet. Which means you can move the cursor to an absolute position or relative to the current cursor position. If the data in the DB is changed by another thread/process that change won’t be reflected in the data stored in the ResultSet.
  • TYPE_SCROLL_SENSITIVE - The constant indicating the type for a ResultSet object that is scrollable and generally sensitive to changes to the data that underlies the ResultSet. Which means you can move the cursor to an absolute position or relative to the current cursor position. If the data in the DB is changed by another thread/process that change is reflected in the data stored in the ResultSet.

Fields for updatable ResultSet

  • CONCUR_READ_ONLY - The constant indicating the concurrency mode for a ResultSet object that may NOT be updated.
  • CONCUR_UPDATABLE - The constant indicating the concurrency mode for a ResultSet object that may be updated.

Example code

Let’s see an example with scrollable resultset, DB used here is MySql, schema is netjs and table is Employee.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCResultSet {

 public static void main(String[] args) {
  try(Connection connection = DriverManager.getConnection(
      "jdbc:mysql://localhost:3306/netjs", "root", "admin")){
   // creating Statement
   Statement stmt = connection.createStatement(
                           ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);  
   
   // Executing Query
   ResultSet rs = stmt.executeQuery("Select * from Employee");
   System.out.println("Displaying all rows");
   // Processing Resultset
   while(rs.next()){
       System.out.println("id : " + rs.getInt("id") + " Name : " 
        + rs.getString("name") + " Age : " + rs.getInt("age")); 
   }
   // moving to 3rd row
   rs.absolute(3);
   System.out.println("Displaying 3rd row");
   System.out.println("id : " + rs.getInt("id") + " Name : " 
                          + rs.getString("name") + " Age : " + rs.getInt("age")); 
  }catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

Output

Displaying all rows
id : 5 Name : Tom Age : 35
id : 6 Name : Tim Age : 20
id : 7 Name : John Age : 25
id : 8 Name : Johnny Age : 35
id : 17 Name : Johnny Age : 65
Displaying 3rd row
id : 7 Name : John Age : 25

Getter Methods

You would have noticed in the examples how appropriate data type getter method is used (i.e. getInt, getString) for retrieving column values from the current row. You can retrieve value using either the index number of the column or the name of the column.

In general, using the column index will be more efficient. Columns are numbered from 1. Drawback is, any alteration in the table structure will mean change in the indexes in the Java code.

updater methods

There are also updater methods corresponding to the data types which are used when your ResultSet is updatable. Using updater methods you can update the column values then update the row in the DB. Updater methods are used in conjunction with updateRow and insertRow methods.

Example code

Let’s see an example to update a row and insert a row using ResultSet methods.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCResultSetUpdate {

 public static void main(String[] args) {
  try(Connection connection = DriverManager.getConnection(
                   "jdbc:mysql://localhost:3306/netjs", "root", "admin")){
   // creating Statement
   Statement stmt = connection.createStatement(
                          ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);  
   
   // Executing Query
   ResultSet rs = stmt.executeQuery("Select * from Employee");
   System.out.println("Displaying all rows");
   // Processing Resultset
   while(rs.next()){
       System.out.println("id : " + rs.getInt("id") + " Name : " 
                               + rs.getString("name") + " Age : " + rs.getInt("age")); 
   }
   // moving to 3rd row
   rs.absolute(3);
   // updating age column for 3rd row
   rs.updateInt("age", 28);
   rs.updateRow();
   System.out.println("Displaying 3rd row");
   System.out.println("id : " + rs.getInt("id") + " Name : " 
                            + rs.getString("name") + " Age : " + rs.getInt("age"));
   
   /*** Inserting row  ***/
   // moves cursor to the insert row
   rs.moveToInsertRow(); 
     
   //rs.updateInt("id",18); //updates the first column using column name
   rs.updateString(2, "Bob"); //updates the second column using column index
   rs.updateInt("age",45);
   rs.insertRow();
   rs.moveToCurrentRow();
   
  }catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }

 }

}

Other fields of ResultSet interface

Some of the fields are already mentioned with examples, ResultSet has some other fields which are as follows -

  • CLOSE_CURSORS_AT_COMMIT - This constant indicates that open ResultSet will be closed when the current transaction is commited.
  • HOLD_CURSORS_OVER_COMMIT - This constant indicates that open ResultSet will remain open when the current transaction is commited.
  • FETCH_FORWARD - The constant indicating that the rows in a result set will be processed in a forward direction; first-to-last.
  • FETCH_REVERSE - The constant indicating that the rows in a result set will be processed in a reverse direction; last-to-first.
  • FETCH_UNKNOWN - The constant indicating that the order in which rows in a result set will be processed is unknown.

Methods of the ResultSet

Most of the often used methods of the ResultSet are already covered with the examples. Some of the other methods which are used for moving the cursor are as follows -

  • afterLast() - Moves the cursor to the end of this ResultSet object, just after the last row.
  • beforeFirst() - Moves the cursor to the front of this ResultSet object, just before the first row.
  • first() - Moves the cursor to the first row in this ResultSet object.
  • last() - Moves the cursor to the last row in this ResultSet object.
  • moveToCurrentRow() - Moves the cursor to the remembered cursor position, usually the current row.
  • moveToInsertRow() - Moves the cursor to the insert row.
  • next() - Moves the cursor froward one row from its current position.
  • previous() - Moves the cursor to the previous row in this ResultSet object.
  • relative(int rows) - Moves the cursor a relative number of rows, either positive or negative.

Reference : https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html

That's all for this topic ResultSet Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Connection Interface in Java-JDBC
  2. Statement Interface in Java-JDBC
  3. Java JDBC overview - JDBC Tutorial
  4. Types of JDBC Drivers
  5. Data access in Spring framework

You may also like -

>>>Go to Java advance topics page

Statement Interface in Java-JDBC

In the post Java JDBC Steps to Connect to DB we have already seen a complete example using the interfaces Driver, Connection, Statement and ResultSet provided by the JDBC API.

In this post we’ll see Statement interface in detail.

Statement interface

Statement interface resides in java.sql package and it is used to execute a static SQL statement and returning the result of the executed query.

Statement interface has two sub-interfaces CallableStatement and PreparedStatement.

PreparedStatement – PreparedStatement object stores the SQL statement in its pre-compiled state. That way it can efficiently execute the same SQL statement multiple times with different parameters.

CallableStatement - This interface is used to execute SQL stored procedures.

You can get a Statement object by calling the Connection.createStatement() method on the Connection object.

Frequently used methods of the Statement

Mostly you will use the execute methods of the Statement interface to execute queries.

  1. boolean execute(String sql) - Executes the given SQL statement (it can be any kind of SQL query), which may return multiple results.
    Returns a boolean which is true if the first result is a ResultSet object; false if it is an update count or there are no results.
  2. ResultSet executeQuery(String sql) - Executes the given SQL statement, which returns a single ResultSet object. If you want to execute a Select SQL query which returns results you should use this method.
  3. int executeUpdate(String sql) - Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
    Returns an int denoting either the row count for the rows that are inserted, deleted, updated or returns 0 if nothing is returned.
    Note:This method cannot be called on a PreparedStatement or CallableStatement.
  4. int[] executeBatch() - Submits a batch of commands to the database for execution and if all commands execute successfully, returns an array of update counts.

Example with execute(), executeUpdate and executeQuery methods

Let’s see an example where SQL statements are executed using execute(), executeUpdate and executeQuery methods. In the example -

Using execute() method a SQL statement is execute and then the boolean value is checked.

Using executeUpdate() method insert, update and delete statements are executed and row count of the affected rows is displayed.

Using executeQuery() method select statement is executed and the returned ResultSet is processed.

Java code

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCStmt {
 
 public static void main(String[] args) {
        Connection connection = null;
        try {
            // Loading driver
            Class.forName("com.mysql.jdbc.Driver");
   
            // Creating connection
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                         "root", "admin");
  
            // creating Statement
            Statement stmt = connection.createStatement();  
            
            /** execute method **/
            boolean flag = stmt.execute("Update Employee set age = 40 where id in (5, 6)");
            if(flag == false){
             System.out.println("Updated rows " + stmt.getUpdateCount() );
            }
            
            /** executeUpdate method **/
            // Insert
            int count = stmt.executeUpdate("Insert into employee(name, age) values('Kim', 23)");
            System.out.println("Rows Inserted " + count);
            
            // update
            count = stmt.executeUpdate("Update Employee set age = 35 where id = 17");
            System.out.println("Rows Updated " + count);
            
            //delete
            count = stmt.executeUpdate("Delete from Employee where id = 5");
            System.out.println("Rows Deleted " + count);
            
            /** executeQuery method **/
            // Executing Query
            ResultSet rs = stmt.executeQuery("Select * from Employee");
   
            // Processing Resultset
            while(rs.next()){
               System.out.println("id : " + rs.getInt("id") + " Name : " 
                + rs.getString("name") + " Age : " + rs.getInt("age")); 
            }
    
       } catch (ClassNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
       } catch (SQLException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }finally{
          if(connection != null){
           //closing connection 
           try {
            connection.close();
           } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
           }
          } // if condition
       }// finally

    }
}

Reference : https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html

That's all for this topic Statement Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Connection Interface in Java-JDBC
  2. Java JDBC overview - JDBC Tutorial
  3. Types of JDBC Drivers
  4. Data access in Spring framework

You may also like -

>>>Go to Java advance topics page

Tuesday, 12 December 2017

Connection Interface in Java-JDBC

In the post Java JDBC Steps to Connect to DB we have already seen a complete example using the interfaces Driver, Connection, Statement and ResultSet provided by the JDBC API.

In this post we’ll see Connection interface in detail.

Connection interface

Connection interface resides in java.sql package and it represents a session with a specific database you are connecting to. SQL statements that you want to execute, results that are returned all that happens with in the context of a connection.

You can get a Connection object by using the getConnection() method of the DriverManager class.

Using Connection class object -

  • You can get the object of Statement
  • You can get the information about the database it is connecting to
  • Connection also provides method for transaction management

Fields in the Connection interface

Connection interface provides a set of fields for specifying transaction isolation level -

  • TRANSACTION_NONE - A constant indicating that transactions are not supported.
  • TRANSACTION_READ_COMMITTED - A constant indicating that dirty reads are prevented; non-repeatable reads and phantom reads can occur.
  • TRANSACTION_READ_UNCOMMITTED - A constant indicating that dirty reads, non-repeatable reads and phantom reads can occur.
  • TRANSACTION_REPEATABLE_READ - A constant indicating that dirty reads and non-repeatable reads are prevented; phantom reads can occur.
  • TRANSACTION_SERIALIZABLE - A constant indicating that dirty reads, non-repeatable reads and phantom reads are prevented.

Frequently used methods of the Connection

Some of the frequently used methods of the Connection are as follows -

For creating statement

  • createStatement() - Creates a Statement object for sending SQL statements to the database.
  • prepareStatement(String sql) - Creates a PreparedStatement object for sending parameterized SQL statements to the database.
  • prepareCall(String sql) - Creates a CallableStatement object for calling database stored procedures.
There are also overloaded variant of these methods where you can specify the type of ResultSet and its concurrency level.

For getting information about the DB

  • getMetaData() - Returns a DatabaseMetaData object containing metadata about the connected database.

For transaction management

  • setAutoCommit(boolean autoCommit) - Sets this connection's commit mode to true or false.
  • setTransactionIsolation(int level) - Attempts to changes the transaction isolation level for this Connection object to the one given.
  • rollback() - Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object.
  • commit() - Makes all changes made since the previous commit/rollback permanent and releases any database locks currently held by this Connection object.

Reference : https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html

That's all for this topic Connection Interface in Java-JDBC. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java JDBC overview - JDBC Tutorial
  2. Types of JDBC Drivers
  3. Data access in Spring framework

You may also like -

>>>Go to Java advance topics page

Saturday, 9 December 2017

Java JDBC Steps to Connect to DB

JDBC API provides a set of interfaces and classes for connecting to DB, creating SQL statement, executing created SQL statement in database, returning the results and processing that ResultSet.

Interfaces provided by JDBC for these steps are Driver (That is the interface implemented by the database vendors to provide a JDBC driver for specific databases), Connection, Statement and ResultSet.

The steps for connecting to DB and fetching results using JDBC can be summarized as follows -

  • Loading driver
  • Creating connection to DB
  • Creating Statement
  • Executing Query
  • Processing ResultSet
  • Closing connection

Loading driver

First thing you need to do is to load a JDBC driver for the DB you are connecting to. You can use forName() method provided by class Class to do that.

General form using Class.forName()

class.forName(“JDBC Driver Class”);

Using registerDriver() method

You can also use registerDriver() method provided by DriverManager class to load the appropriate driver. Note that it is a static method.

General form using registerDriver() method

DriverManager.registerDriver(Driver class object);

Driver classes for some of the databases are as follows -

  • MySql – com.mysql.jdbc.Driver (You need to download MySQL Connector/J jar mysql-connector-java-5.1.39.jar (Please check for the latest version) which will have the JDBC driver).
  • Oracle – oracle.jdbc.driver.OracleDriver (You need to download ojdbc8.jar or higher version for Java 8 and JDBC 4.2).
  • DB2 – com.ibm.db2.jcc.DB2Driver (You need to download db2jcc.jar for the DB2 JDBC driver).

Example

For loading Oracle driver using Class.forName() method -

Class.forName(“oracle.jdbc.driver.OracleDriver”);

Since the driver class is not explicitly used in the program that’s why JVM won’t load it automatically. JVM will automatically load the classes that are used in the program. That is the reason you need to load driver class using class.forName() that way you explicitly tell JVM to load this driver class.

For loading MySql driver using resgisterDriver method -

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

If you are using JDBC 4.x (Version Java 6 or higher) then actually you don’t need to explicitly load the JDBC driver. As Automatic loading of JDBC drivers is supported from JDBC 4 you just need to have the appropriate jar in the class path. So loading driver step is optional from Java 6 onwards make sure that automatic loading is supported by the driver you are using.

Creating connection

Once you have registered the driver, second step is to open a connection to the DB. For that you can use the static method getConnection() of the java.sql.DriverManager class.

General form of getConnection method

DriverManager.getConnection(DB_URL, DBuser, password)

URL Pattern for some of the databases

  • Oracle – jdbc:oracle:<drivertype>:@<database>

    As example - Connecting user scott with password tiger to a database with SID orcl through port 1521 of host myhost, using the Thin driver.

    Connection connection = DriverManager.getConnection
         ("jdbc:oracle:thin:@myhost:1521:orcl", "scott", "tiger");
    
  • MySQL – jdbc:mysql://hostname:portnumber/dbName

    As example - Connecting user root with password admin to a database test through port 3306 of host localhost.

    Connection connection = DriverManager.getConnection
         ("jdbc:mysql://localhost:3306/test", "root", "admin");
    
  • DB2 – jdbc:db2://hostname:portnumber/dbName

    As example - Connecting user dbadmin with password dbadmin to a database mydb through port 5021 of host myhost.

    Connection connection = DriverManager.getConnection
         ("jdbc:db2://myhost:5021/mydb","dbadmin","dbadmin");
    

Creating Statement

Once Connection object is created that can be used to create an object of Statement. Statement object is needed for specifying the SQL statement that has to be executed by the DB.

Statement statement = connection.createStatement();

Executing Query

To execute a query you need to call execute method of the Statement class.

You can call executeUpdate(String sql) method for INSERT, DELETE, UPDATE or DDL (Data Definition Language) SQL statements. This method returns an integer representing the number of rows affected by the SQL statement so you will know how many rows are inserted, deleted or updated.

You can call executeQuery(String SQL) method for SELECT sql queries. This method returns a ResultSet.

As example -

  1. To create a table employee
    statement.executeUpdate(“CREATE TABLE employee (id int(11), name varchar(35), age int(11))”);
    
  2. To get data for all employees
    ResultSet rs = statement.executeQuery("Select * from Employee"); 
    

Processing ResultSet

Once the query is executed and you have the ResultSet you access the data in a ResultSet object through a cursor. This cursor is a pointer that points to one row of data in the ResultSet object. Initially, the cursor is positioned before the first row. You can use next method to move to the next row of the ResultSet. There are various getter methods based on data type to get the value of the current row.

As example -

If you want to iterate the ResultSet returned from the above query for getting all the employees.

while(rs.next()){
 System.out.println("id : " + rs.getInt("id") + " Name : " + rs.getString("name") + " Age : " + rs.getInt("age"));
}

In the example getter method are using the column labels to retrieve the values you can also use the column indexes to get the values, index starts from 1.

while(rs.next()){
 System.out.println("id : " + rs.getInt(1) + " Name : " + rs.getString(2) + " Age : " + rs.getInt(3));
}

Closing the connection

Once you have the processed the ResultSet you can close the connection.

connection.close();

It’s better to close an opened connection in a finally block. That ensures that the connection is closed even if there is an exception in the code.

Putting everything together

Let’s put all these steps together in a Java program. DB used here is MySql, schema is netjs and table is Employee.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCCon {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            // Loading driver
            Class.forName("com.mysql.jdbc.Driver");
            // Another way
            //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
   
            // Creating connection
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/netjs", 
                         "root", "admin");
  
            // creating Statement
            Statement stmt = connection.createStatement();  
   
            // Executing Query
            ResultSet rs = stmt.executeQuery("Select * from Employee");
   
            // Processing Resultset
            while(rs.next()){
               System.out.println("id : " + rs.getInt("id") + " Name : " 
                + rs.getString("name") + " Age : " + rs.getInt("age")); 
            }
    
       } catch (ClassNotFoundException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
       } catch (SQLException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }finally{
          if(connection != null){
             //closing connection 
             try {
               connection.close();
             } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
             }
          }
       }

    }

}

You can put DB credential information in a properties file and read it from there. Refer How to read Properties file in Java to see how to read properties file in Java.

Using try-with-resources

If you are using Java 7 or above, you can use a try-with-resources statement to automatically close Connection, Statement, and ResultSet objects, regardless of whether an SQLException has been thrown.

Example code

If we modify the above code to include try-with-resources then we can get rid of finally block used to close the connection.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCCon {

    public static void main(String[] args) {
       try(Connection connection = DriverManager.getConnection(
           "jdbc:mysql://localhost:3306/netjs", "root", "admin"))
       {
          // creating Statement
          Statement stmt = connection.createStatement();  
   
          // Executing Query
          ResultSet rs = stmt.executeQuery("Select * from Employee");
   
          // Processing Resultset
          while(rs.next()){
             System.out.println("id : " + rs.getInt("id") + " Name : " 
                   + rs.getString("name") + " Age : " + rs.getInt("age")); 
          }
       }catch (SQLException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
       }
    }
}

Here note that Class.forName("com.mysql.jdbc.Driver"); statement is also excluded as that is also optional, from JDBC 4.0 drivers which are in the class path are automatically loaded.

That's all for this topic Java JDBC Steps to Connect to DB. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java JDBC overview - JDBC Tutorial
  2. Types of JDBC Drivers
  3. Insert\Update using JDBCTemplate in Spring framework

You may also like -

>>>Go to Java advance topics page

Java JDBC overview - JDBC Tutorial

JDBC is the Java API for developing Java applications that access relational databases.

Why use JDBC

JDBC provides developers with a uniform interface to connect with different relational databases like Oracle, MySQL, DB2, Access etc.

JDBC provides a set of interfaces and classes that standardize the interaction with different databases and abstracts you as a developer with the inner working of the proprietary databases. You just need to know the standard JDBC steps to connect to database, query it in order to fetch results or update DB. Note here that the SQL may differ according to the DB used.

JDBC Driver

In Order to connect to database JDBC uses JDBC driver. Since JDBC driver acts as a connector between JDBC and proprietary databases JDBC drivers are DB specific and generally provided by the DB vendor itself.

As example – In order to connect to connect to MySql DB you will need a MySql JDBC connector driver which is bundled in the mysql-connector-javaXXX.jar.

The interaction of JDBC with the database using JDBC driver can be pictorially represented as follows -

JDBC Drivers

Packages in JDBC API

The JDBC API is comprised of two packages:

  • java.sql - Referred to as the JDBC core API
  • javax.sql - Referred to as the JDBC Optional Package API
You automatically get both packages when you download the Java Platform Standard Edition (Java SE).

Changes in JDBC 4.x

The current version of JDBC which comes bundled with Java 8 is JDBC 4.2. There are some noticeable changes in the 4.x versions like -

  1. Addition of the java.sql.SQLType Interface
  2. Addition of the java.sql.JDBCType Enum – Using SQLType interface and JDBCType Enum you can identify the generic SQL types like CLOB, REF_CURSOR, TINYINT, VARCHAR etc.
  3. You can use try-with-resources statement to automatically close resources of type Connection, ResultSet, and Statement.
  4. Automatic loading of JDBC drivers on the class path.

Steps for connecting to DB

JDBC API provides a set of interfaces and classes for connecting to DB, creating SQL statement, executing created SQL statement in database, returning the results and processing that ResultSet.

These steps can be summarized as follows -

  • Loading driver
  • Creating connection to DB
  • Creating Statement
  • Executing Query
  • Processing ResultSet
  • Closing connection

Refer Java JDBC Steps to Connect to DB to see these steps in details and a JDBC example Java program.

A pictorial representation of these steps can be represented as follows.

JDBC steps

That's all for this topic Java JDBC overview - JDBC Tutorial. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Types of JDBC Drivers
  2. Java JDBC Steps to Connect to DB
  3. Data access in Spring framework
  4. Select query using JDBCTemplate in Spring framework

You may also like -

>>>Go to Java advance topics page

Types of JDBC Drivers

JDBC driver is an implementation of the Driver interface in the java.sql package.

Every database vendor should provide a JDBC driver for their DBMS and each JDBC driver should supply a class that implements the Driver interface.

There are many possible implementations of JDBC driver, these implementations can be categorized into four types.

  • Type 1 driver
  • Type 2 driver
  • Type 3 driver
  • Type 4 driver

Type 1 Driver

Type 1 driver is a type of JDBC driver that implements the JDBC API as a mapping to another DB access API.

As example - The JDBC-ODBC Bridge driver that maps JDBC API requests to ODBC requests. Here note that ODBC (Open Database Connectivity) is another standard API for accessing databases which is developed by Microsoft.

Type 1 drivers type are generally dependent on a native library, which limits their portability.

DB access through Type 1 driver

Type 2 Driver

Type 2 drivers are written partly in Java and partly in native code. Native client library specific to the data source to which connection is made is used by Type 2 JDBC drivers.

As example - Oracle's OCI (Oracle Call Interface) client-side driver is an example of a Type 2 driver.

Since native code is used by Type 2 drivers, their portability is limited.

DB access through Type 2 driver

Type 3 Driver

Type 3 driver has a client that is written in Java and that connects to a middleware server using a database independent protocol. Middleware server in turn communicates with the data source.

The drawback of Type 3 driver is that the middleware server has to be DB specific.

There are two stages in Type 3 driver. First, where Java application connects to Type 3 driver which in turn connects to middleware server. Its the sever which translates the request to DB specific request making the whole process slower.

DB access through Type 3 driver

Type 4 Driver

Type 4 drivers are written completely in Java so no native code library or middleware server is needed, that is why type 4 drivers are also known as thin drivers. Type 4 drivers themselves implement the network protocol for a specific data source.

DB access through Type 4 driver

Reference : https://docs.oracle.com/javase/tutorial/jdbc/basics/gettingstarted.html

That's all for this topic Types of JDBC Drivers. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Java JDBC overview - JDBC Tutorial
  2. Java JDBC Steps to Connect to DB
  3. Data access in Spring framework

You may also like -

>>>Go to Java advance topics page

Tuesday, 5 December 2017

Livelock in Java Multi-Threading

Livelock in Java multi-threading is a situation where two or more threads are acting on a response to an action of each other and not able to make any progress because of that.

How livelock is different from deadlock in Java multi-threading is that in case of deadlock threads get blocked whereas in case of livelock threads are active but busy responding to each other thus not making any progress.

Example of livelock

Let’s see an example of livelock in threads to understand it. A classic example to explain livelock is a multi-threaded application to deposit and withdraw money from accounts with a provision to rollback the transaction if transaction doesn’t go through.

Java code

import java.util.concurrent.locks.ReentrantLock;

public class LivelockDemo {

    public static void main(String[] args) {
        Account acct1 = new Account(101, 5000);
        Account acct2 = new Account(102, 7000);
        // Creating two threads
        Thread thread1 = new Thread(new Operation(acct1, acct2, 100));
        Thread thread2 = new Thread(new Operation(acct2, acct1, 100));

        thread1.start();
        thread2.start();
    }

}

class Account{
    int acctNum;
    int balance;
    ReentrantLock lock = new ReentrantLock();
    Account(int acctNum, int balance){
        this.acctNum = acctNum;
        this.balance = balance;
    }
    
    /**
     * Method for depositing amount
     * @param amount
     * @return
     */
    public boolean deposit(int amount){
        System.out.println("In deposit method");
        if(this.lock.tryLock()){
            try {
                // Simulating some delay
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("deposit in " + this.acctNum + " for " 
              + Thread.currentThread().getName());
            this.balance = balance + amount;
            return true;
        }
        return false;
    }
    
    /**
     * Method for withdrawing amount
     * @param amount
     * @return
     */
    public boolean withdraw(int amount){
        System.out.println("In withdraw method");
        if(this.lock.tryLock()){
            try {
                // Simulating some delay
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("Withdrawn from " + this.acctNum + " for " 
              + Thread.currentThread().getName());
            this.balance = balance - amount;
            return true;
        }
        return false;
    }
    
    public boolean transact(Account targetAcct, int amount){
        //System.out.println("In transact method " + targetAcct);
        boolean flag = false;
        // If you can withdraw from the source account and
        // deposit it into target account then only return true        
        if(this.withdraw(amount) && targetAcct.deposit(amount)){
                flag = true;
        }else{
            // Rollback and deposit the withdrawn amount back in source account    
            System.out.println("Failed to deposit in " + targetAcct.acctNum + 
              " depositing back in account " + this.acctNum);
            this.deposit(amount);
            
        }
        return flag;
    }
}

class Operation implements Runnable{
    Account sourceAccount;
    Account targetAccount;
    int amount;
    Operation(Account sourceAccount, Account targetAccount, int amount){
        this.sourceAccount = sourceAccount;
        this.targetAccount = targetAccount;
        this.amount = amount;
    }

    @Override
    public void run() {
        
        sourceAccount.transact(targetAccount, amount);
    }
    
}

Output

In withdraw method
In withdraw method
Withdrawn from 102 for Thread-1
In deposit method
Withdrawn from 101 for Thread-0
In deposit method
Failed to deposit in 101 depositing back in account 102
In deposit method
Failed to deposit in 102 depositing back in account 101
In deposit method
deposit in 102 for Thread-1
deposit in 101 for Thread-0

Here you can see that you have two threads where one is withdrawing amount from Account 101 and depositing it in 102 and the other thread is withdrawing amount from Account 102 and depositing it in 101. Threads are failing to complete the transaction because of not able to get the lock and rolling back the transaction.

In the above example transaction is not run in the loop so the threads make just one attempt, you can change the run method as follows and see how both threads keep trying and rolling back the transactions without making any real progress.

public void run() {
 while(!sourceAccount.transact(targetAccount, amount)){
  continue;
 } 
}

If you run your code with these changes in run() method you will have to terminate your program to come out of the loop.

Output

In withdraw method
In withdraw method
Withdrawn from 101 for Thread-0
Withdrawn from 102 for Thread-1
In deposit method
In deposit method
Failed to deposit in 101 depositing back in account 102
In deposit method
Failed to deposit in 102 depositing back in account 101
In deposit method
deposit in 102 for Thread-1
In withdraw method
deposit in 101 for Thread-0
In withdraw method
Withdrawn from 101 for Thread-0
In deposit method
Withdrawn from 102 for Thread-1
In deposit method
Failed to deposit in 102 depositing back in account 101
In deposit method
Failed to deposit in 101 depositing back in account 102
In deposit method
deposit in 102 for Thread-1
In withdraw method
deposit in 101 for Thread-0
In withdraw method
Withdrawn from 102 for Thread-1
In deposit method
Withdrawn from 101 for Thread-0
In deposit method
Failed to deposit in 101 depositing back in account 102
In deposit method
Failed to deposit in 102 depositing back in account 101
In deposit method
deposit in 101 for Thread-0
In withdraw method
deposit in 102 for Thread-1
In withdraw method
Withdrawn from 101 for Thread-0
In deposit method
Withdrawn from 102 for Thread-1
In deposit method

That's all for this topic Livelock in Java Multi-Threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Thread Starvation in Java Multi-Threading
  2. Why wait(), notify() and notifyAll() methods are in Object class
  3. Race condition in Java multi-threading
  4. ReentrantLock in Java concurrency
  5. Java Multi-threading interview questions

You may also like -

>>>Go to Java advance topics page

Thursday, 30 November 2017

Find Maximum and Minimum Numbers in the Given Matrix - Java Program

This post is about writing a Java program to find the maximum and minimum number in the given matrix (2D Array).

Solution to find largest and smallest number

Logic here is to have two variables for maximum and minimum numbers, initially assign the element at the first index of the matrix to both the variables.

Then iterate the matrix one row at a time and compare each column element with the max number if max number is less than the column element then assign column element to the max number.

If max number is greater than the column element then check if minimum number is greater than the column element, if yes then assign column element to the minimum number.

Java code

In the first part of the program matrix elements are entered and the end matrix is displayed then the maximum and minimum numbers are found using the above mentioned logic.

public class MatrixMinMax {

 public static void main(String[] args) {
  int rows; 
  int columns;
  Scanner scanner = new Scanner (System.in);
  // 
  System.out.println("Enter number of rows: ");
  rows = scanner.nextInt(); 
  
  System.out.println("Enter number of columns: "); 
  columns = scanner.nextInt(); 
  
  int[][] matrix = new int [rows][columns];
  
  System.out.println("Enter matrix numbers: "); 
  for (int i = 0; i < rows; i++) {
   System.out.println("Enter numbers for row - " + (i+1) + " and press enter"); 
   for (int j = 0; j < columns; j++) {
    matrix[i][j] = scanner.nextInt();
   }
  }
  scanner.close();
  // Displaying entered matrix
  System.out.println("Matrix as entered");
     for (int i = 0; i < matrix .length; i++) {
        System.out.println();
        for (int j = 0; j < matrix[i].length; j++) {
           System.out.print(matrix[i][j] + " ");
        }
     }
     System.out.println();
     findMinMax(matrix);

 }
 
 // Method to find max and min
 private static void findMinMax(int[][] matrix){
  //  start by assigning the first matrix element
  // to both the variables
  int maxNum = matrix[0][0];
  int minNum = matrix[0][0];
  for (int i = 0; i < matrix.length; i++) {
   for (int j = 0; j < matrix[i].length; j++) {
    if(maxNum < matrix[i][j]){
     maxNum = matrix[i][j];
    }else if(minNum > matrix[i][j]){
     minNum = matrix[i][j];
    }
   }
  }
  System.out.println("Largest number:  " 
    + maxNum + " Smallest number: " + minNum);

 }

}

Output

Enter number of rows: 
3
Enter number of columns: 

3
Enter matrix numbers: 
Enter numbers for row - 1 and press enter
2 5 8
Enter numbers for row - 2 and press enter
17 4 9
Enter numbers for row - 3 and press enter
22 34 3
Matrix as entered

2 5 8 
17 4 9 
22 34 3 
Largest number:  34 Smallest number: 2

That's all for this topic Find Maximum and Minimum Number in the Given Matrix - Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Matrix Multiplication Java Program
  2. Find Largest and Second Largest Number in Given Array - Java Program
  3. How to Find Common Elements Between Two Arrays - Java Program
  4. Finding duplicate elements in an array - Java Program
  5. How to remove elements from an array - Java Program

You may also like -

>>>Go to Java Programs page

Monday, 27 November 2017

Garbage Collection in Java

In the post Heap Memory Allocation in Java I have already explained why heap is divided into generations and how it helps in garbage collection by adopting an approach known as “generational collection”.

In this post we’ll see more details about garage collection in Java, basic process of garbage collection, garbage collection tuning and types of garbage collectors available.

What is Garbage Collection

Garbage collection in Java is an automatic process of inspecting the heap memory and identifying which objects are in use and which are not and deleting the unused objects after identification.

Here object which is in use (referenced object) means that a part of your program is still holding a reference to the object. Unused object (unreferenced object) means not referenced by any part of your program and can be deleted safely.

Basic Garbage Collection Process

Basic garbage collection process has three steps -

  1. Marking
  2. Sweeping
  3. Compacting

Marking

The first step in the garbage collection process is called marking. In this step GC iterates through the memory and identifies which objects are still in use and which objects are unused.

Sweeping

In this step of sweeping (normal deletion) objects which are already marked as unused in the “marking” step are removed in order to free space.

Compacting

Deleting the unused objects fragments the memory which results in further memory allocation which are not contiguous. That is why there is another step which moves the reference objects together which results in having a contiguous free space thus making the new memory allocation much easier and faster.

garbage collection compacting process

Performance parameters for GC

There are two goals for any application with respect to garbage collection –

  • Maximum pause time goal
  • Application throughput goal

Maximum Pause Time Goal

All minor garbage collections and major garbage collections are "Stop the World" events which means all application threads are stopped until the garbage collection completes. So, the goal here is to minimize this pause time or restrict it by putting an upper limit.

That is what this parameter does; maximum pause time goal is to limit the longest of these pauses.

Note here that only parallel collector provides a command line option to specify a maximum pause time goal.

Command line option

-XX:MaxGCPauseMillis=<nnn> 

This option is a hint to the garbage collector that pause times of <nnn> milliseconds or less are desired.

Throughput Goal

Since garbage collection is "Stop the world event" stopping all the application threads so we can divide the total time into -

  • The time spent collecting garbage
  • The application time

The throughput goal is measured in terms of the time spent collecting garbage and the time spent outside of garbage collection.

Note here that only parallel collector provides a command line option to specify a throughput goal.

Command line option

-XX:GCTimeRatio=<nnn>

The ratio of garbage collection time to application time is 1 / (1 + <nnn>). For example, -XX:GCTimeRatio=9 sets a goal of 1/10th or 10% of the total time for garbage collection.

Available garbage collectors

The Java HotSpot VM has three different types of collectors -

  1. Serial GC
  2. Parallel GC also known as Throughput Collector.
  3. Mostly Concurrent Collector – Java HotSpot offers two types of mostly concurrent collector.
    • Concurrent Mark Sweep (CMS) Collector
    • Garbage First, Garbage collector (G1 Collector)

Serial Collector

The serial collector uses a single thread to do both minor and major collections. The serial collector is best-suited to single processor machines, because it cannot take advantage of multiprocessor hardware. Since only a single thread performs garbage collection so Serial GC is most suited for applications that do not have low pause time requirements.

Command Line Switches

The serial collector is selected by default on certain hardware (client machines) and operating system configurations. Serial collector can be explicitly enabled with the option

-XX:+UseSerialGC.

Parallel Collector

In parallel collector (also known as the throughput collector) multiple threads are used for garbage collection.

The command line option to enable parallel collector is -XX:+UseParallelGC.

By default, with this option, both minor and major collections are executed in parallel to further reduce garbage collection overhead.

The feature that enables the parallel collector to perform major collections in parallel is known as parallel compaction. If parallel compaction is not enabled then major collections are performed using a single thread.

Command line option to turn off parallel compaction is : -XX:+UseParallelOldGC.

Only parallel collector provides command line options to tune the performance parameters as stated above.

Command Line Switches

  • Maximum Garbage Collection Pause Time: The maximum pause time goal is specified with the command-line option -XX:MaxGCPauseMillis=<N>.
  • Throughput goal: The throughput goal is specified by the command-line option -XX:GCTimeRatio=<N>

Concurrent Mark Sweep (CMS) Collector

Concurrent Mark Sweep (CMS) Collector, as the name suggests, performs garbage collection concurrently while the application is running. Since application also keep running that results in low pause time but the application throughput is affected because processor resources are shared.

This collector should be considered for any application with a low pause time requirement.

Like other available collectors the CMS collector is generational; thus both minor and major collections occur. The CMS collector attempts to reduce pause times due to major collections by using separate garbage collector threads to trace the reachable objects concurrently with the execution of the application threads. CMS (Concurrent Mark Sweep) garbage collection does not do compaction.

Pauses in CMS collector

The CMS collector pauses an application twice during a concurrent collection cycle. The first pause marks those objects as live which are directly reachable from the roots and from elsewhere in the heap. This first pause is referred to as the initial mark pause.

The second pause comes at the end of the concurrent tracing phase and finds objects that were missed by the concurrent tracing due to updates by the application threads of references in an object after the CMS collector had finished tracing that object. This second pause is referred to as the remark pause.

Command Line Switches

  • The command line option to enable CMS collector is -XX:+UseConcMarkSweepGC.
  • Command line option to set the number of threads -XX:ParallelCMSThreads=<n>

Garbage-First Garbage Collector

The Garbage-First (G1) garbage collector is a server-style garbage collector which is suited for multiprocessor machines with large memories. G1 garbage collector minimizes the garbage collection (GC) pause time while achieving high throughput at the same time.

It minimizes the garbage collection (GC) pause time by trying to adhere to pause time goals which is set using the flag MaxGCPauseMillis.

Technique used by G1 collector

Technique used by G1 collector to achieve high performance and pause time goals is explained below -

G1 Collector partitions the heap into a set of equally sized heap regions. Initially G1 performs a concurrent global marking throughout the heap to determine which objects are still referenced and which are not (unreferenced). Once the marking is done G1 knows which regions are mostly empty. It collects these mostly empty regions first thus the name Garbage-First. By using this method of garbage collection G1 frees the large amount of free space by sweeping only a small region of heap.

G1 tries to adhere to the specified pause time target (defined by using flag MaxGCPauseMillis) by using a pause prediction model. It calculates how many regions can be collected within the given pause time limit and collects only those regions.

G1 is generational in a logical sense

As already stated heap is partitioned into a set of equally sized heap regions. A set of empty regions is designated as the logical young generation. Objects are allocated from that logical young generation and that young generation (those regions of heap) is garbage collected when it is full. In some cases, regions outside the set of young regions (regions designated as tenured generation) can be garbage collected at the same time. This is referred to as a mixed collection.

G1 collector also compacts the memory by copying the live objects to selected, initially empty regions.

Command Line Switches

The command line option to enable G1 collector is -XX:+UseG1GC.

Reference -

http://www.oracle.com/technetwork/articles/java/architect-evans-pt1-2266278.html
https://docs.oracle.com/cd/E15289_01/doc.40/e15058/underst_jit.htm

That's all for this topic Garbage Collection in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Just In Time Compiler (JIT) in Java
  2. JVM Run-Time Data Areas - Java Memory Allocation
  3. Heap Memory Allocation in Java
  4. How to run javap programmatically from Java Program
  5. Core Java Basics Interview Questions

You may also like -

>>>Go to Java advance topics page

Friday, 17 November 2017

Find Largest and Smallest Number in the Given Array - Java Program

This post is about writing a Java program to find the largest and the smallest number in the given array or it can also be rephrased as - Find the maximum and minimum number in the given array.

Condition here is that you should not be using any inbuilt Java classes (i.e. Arrays.sort) or any data structure.

Solution to find the largest and the smallest number

Logic here is to have two variables for maximum and minimum number, initially assign the element at the first index of the array to both the variables.

Then iterate the array and compare each array element with the max number if max number is less than the array element then assign array element to the max number.

If max number is greater than the array element then check if minimum number is greater than the array element, if yes then assign array element to the minimum number.

Java code

public class FindMaxMin {

 public static void main(String[] args) {
  int numArr[] = {56, 36, 48, 49, 29, 458, 56, 4, 7};
  
  // start by assigning the first array element
  // to both the variables
  int maxNum = numArr[0];
  int minNum = numArr[0];
  // start with next index (i.e. i = 1)
  for(int i = 1; i < numArr.length; i++){
   if(maxNum < numArr[i]){
    maxNum = numArr[i];
   }else if(minNum > numArr[i]){
    minNum = numArr[i];
   }
   
   
  }
  System.out.println("Largest number -  " 
     + maxNum + " Smallest number - " + minNum);

 }

}

Output

Largest number -  458 Smallest number - 4

That's all for this topic Find Largest and Smallest Number in the Given Array - Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Find Largest and Second Largest Number in Given Array - Java Program
  2. How to Find Common Elements Between Two Arrays - Java Program
  3. Finding duplicate elements in an array - Java Program
  4. How to remove elements from an array - Java Program
  5. Matrix Multiplication Java Program

You may also like -

>>>Go to Java Programs page

Tuesday, 14 November 2017

Find Largest and Second Largest Number in Given Array - Java Program

This post is about writing a Java program to find the top two numbers (largest and second largest) in the given array.

Condition here is that you should not be using any inbuilt Java classes or methods (i.e. Arrays.sort) or any data structure.

Solution to find largest and second largest number

Logic here is to have two variables for first and second number and iterate the array. Compare each array element with the first number if first number is less than the array element then assign existing first number to second number and array element to the first number.

If first number is greater than the array element then check if second element is less than the array element, if yes then assign array element to the second number.

Java code

public class FindTopTwo {

 public static void main(String[] args) {
  int numArr[] = {2, 5, 14, 1, 26, 65, 123, 6};
  int firstNum = 0;
  int secondNum = 0;
  
  for(int i = 0; i < numArr.length; i++){
   if(firstNum < numArr[i]){
    secondNum = firstNum;
    firstNum = numArr[i];
   }else if(secondNum < numArr[i]){
    secondNum = numArr[i];
   }
   
   
  }
  System.out.println("Top two numbers : First -  " 
     + firstNum + " Second " + secondNum);

 }

}

Output

Top two numbers : First -  123 Second 65

That's all for this topic Find Largest and Second Largest Number in Given Array - Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to remove elements from an array - Java Program
  2. Matrix Addition - Java Program
  3. How to Find Common Elements Between Two Arrays - Java Program
  4. Arrange Non-Negative Integers to Form Largest Number - Java Program

You may also like -

>>>Go to Java Programs page

Thursday, 9 November 2017

Difference Between Two Dates - Java Program

In this post we’ll see how to calculate date-time difference between two dates in Java using the new date and time API in Java 8 -

Using Java 8 Period and Duration classes

If you are using Java 8 then you can use new data and time API classes Period and Duration.

Here Period class models amount of time in terms of years, months and days and Duration class models amount of time in terms of seconds and nanoseconds.

Java code

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;

public class DateDiff {
 public static void main(String[] args) {
  LocalDateTime dateTime1 = LocalDateTime.of(2016, 8, 28, 13, 15, 55);
  LocalDateTime dateTime2 = LocalDateTime.of(2016, 8, 29, 17, 18, 14);

  getPeriod(dateTime1.toLocalDate(), dateTime2.toLocalDate());
  getTime(dateTime1.toLocalTime(), dateTime2.toLocalTime());
 }
 
 /**
  * 
  * @param date1
  * @param date2
  */
 private static void getPeriod(LocalDate date1, LocalDate date2){
  Period p = Period.between(date1, date2);
  System.out.println("Year " + p.getYears());
  System.out.println("Months " + p.getMonths());
  System.out.println("Days " + p.getDays());   
 }
 /**
  *   
  * @param time1
  * @param time2
  */
 private static void getTime(LocalTime time1, LocalTime time2){
   
  Duration d = Duration.between(time1, time2);
  long seconds = d.getSeconds();
  //System.out.println("seconds " + seconds);
  // Calculating hours
  System.out.println("Hours " + d.toHours());
  // Calculating Minutes
  System.out.println("Minutes " + ((seconds % 3600)/60));
  // Calculating Seconds
  System.out.println("Seconds " + (seconds % 60));

 }
}

Output

Year 0
Months 0
Days 1
Hours 4
Minutes 2
Seconds 19

Running it with another set of dates -

LocalDateTime dateTime1 = LocalDateTime.of(2016, 8, 28, 13, 15, 55);
LocalDateTime dateTime2 = LocalDateTime.of(2017, 10, 5, 15, 12, 59);

Output

Year 1
Months 1
Days 7
Hours 1
Minutes 57
Seconds 4

That's all for this topic Difference Between Two Dates - Java Program. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. How to convert date and time between different time-zones in Java
  2. How to Format Time in AM-PM Format - Java Program
  3. How to format date in Java using SimpleDateFormat
  4. How to convert Date to String in Java
  5. How to find last modified date of a file in Java

You may also like -

>>>Go to Java Programs page

Tuesday, 7 November 2017

Heap Memory Allocation in Java

In the post JVM run-time data areas we have already got a brief idea about the memory areas used while running a Java application. In this post we’ll talk about Heap memory space in detail – How Heap memory is allocated, how garbage collection happens, heap memory tuning and heap memory profiling.

Heap memory allocation

Heap is the JVM run-time data area where the Java objects reside. Apart from Java objects memory for instance variables and arrays is also allocated on the heap. Heap is created on the JVM start-up and shared among all Java Virtual Machine threads.

Heap is divided into two areas (or generations) -

  • Young Space(generation) - The young generation consists of eden and two survivor spaces. Most objects are initially allocated in eden.
  • Old Space (or Tenured generation) – When objects (which have survived garbage collection) residing in young space have reached a certain age threshold they are moved to old space.

These generations have their own memory pool allocated by the JVM.

Heap memory areas

Why memory is managed in generations

Here let’s deviate a little and try to understand why memory is managed in generations and what benefit do we get out of it. In one line it can be explained as these division into generations makes garbage collection more efficient.

As you must be knowing Garbage collection is an automatic storage management system that frees space in the heap by reclaiming memory for objects that are not having any reference. Note that, an object is considered garbage when it can no longer be reached from any pointer in the running program.

A very simplistic garbage collection algorithms will iterate over every reachable object. Any objects left over are considered garbage. With this algorithm the time taken is proportional to the number of live objects in the whole heap.

In order to minimize the time it takes to do garbage collection the approach taken by JVM is known as "generational collection". This approach works on the weak weak generational hypothesis, which states that most objects survive for only a short period of time.

In order to optimize for this hypothesis, memory is managed in generations. Initially objects are allocated in the young generation (Eden space) and most objects die there.

When the young generation fills up, it results in a minor collection (Minor GC) in which only the young generation is collected, that way rather than iterating over the objects in the whole heap only a small portion of the Heap (Young generation) is inspected for dead objects. If the hypothesis stated above holds true then most of the objects will die there and reclaimed with in the younger generation.

Only a small portion of the objects will survive the garbage collection in younger generation and after a certain time lapse will move to tenured generation. Eventually, the tenured generation will fill up and must be garbage collected, that will result in a major collection (Major GC), in which the entire heap is collected.

How garbage collection works on the heap

Now that you know that Heap is divided into generations and how this division helps garbage collector to run more efficiently as GC has to go through only a part of the heap space and within that less space iteration most of the objects (Remember most of the objects die young!) can be garbage collected.

Let’s see in more detail how garbage collection works across these generations and what happens when minor GC is triggered and what happens when major GC is triggered.

  • Within the young generation initially any new objects are allocated to the eden space. Both survivor spaces (S0 and S1) are initially empty.
  • A minor garbage collection is triggered when eden space is filled up. All the unreferenced objects are garbage collected and reference objects are moved to the first survivor space (S0). One survivor space is empty at any time.
  • When the minor garbage collection is triggered next time, all the unreferenced objects are garbage collected and reference objects are moved to the survivor space. Note that this time referenced objects are moved to the second survivor space (S1). There is one more step; objects from the previous minor GC on the first survivor space (S0) have their age incremented and get moved to S1. Note that one survivor space is empty at any time.
  • This process of clearing eden space, moving the referenced objects to one of the survivor spaces, incrementing the age for the surviving objects keeps on repeating with every minor GC. There is also a check for object’s age reaching a certain threshold. Objects that reach the threshold are moved from young generation to the old generation.
  • With every minor GC aged objects will be moved from young to old generation space.
  • When that movement of object fills up the tenured space that triggers a major GC in which the entire heap is collected. Major garbage collection lasts much longer than minor collections because a significantly larger number of objects are involved. Apart from garbage collecting the objects, major GC also compacts the space as it is defragmented from cleaning of the objects.

Refer Garbage Collection in Java to know more about garbage collection process and available garbage collectors in Java

VM Heap Size tuning options

Heap memory will have three things – live objects, dead objects and some portion of the memory which is still free. The JVM heap size determines the frequency of garbage collection and the time spent on collecting garbage.

If you set a large heap size frequency of garbage collection will be less but the time spent on collecting garbage will be more because of the large size (means having more objects to inspect).

On the other hand if you do the opposite then time spent on collecting garbage will be less but frequency will increase as smaller heap will fill faster.

An acceptable heap size is application-specific and should be adjusted using the provided options after analyzing the actual time and frequency of garbage collections.

Java heap size options

  1. Task: Setting initial heap size

    Option: -Xms

    As example: -Xms40m

  2. Task: Setting maximum heap size

    Option: -Xms

    As example: -Xmx512m

    At initialization of the JVM, the entire space for the heap is reserved. The size of the space reserved can be specified with the -Xmx option. If the value provided with the -Xms parameter is smaller than the value provided with the -Xmx parameter, then all of the space that is reserved for the heap is not committed to the virtual machine. The different generationso of the heap (Young and tenured) can grow to that limit (provided with -Xmx) as and when needed.

    It is recommended that you set initial heap size (-Xms) equal to the maximum heap size (-Xmx) to minimize garbage collections.

  3. If you have not given same values for parameters -Xms and -Xmx then the virtual machine will grow or shrink the heap at each garbage collection to try to keep the proportion of free space to live objects within a specific range. The options to set this target ranges are -

  4. Task: To maintain minimum percentage heap free space

    Option: -XX:MinHeapFreeRatio=<minimum>

    As example: -XX:MinHeapFreeRatio=40

  5. Task: To maintain maximum percentage heap free space

    Option: -XX:MaxHeapFreeRatio=<maximum>

    As example: -XX:MaxHeapFreeRatio=70

    With the parameters as used in the example let's try to understand these options better. If the percent of free space in a generation falls below 40%, then the generation will be expanded to maintain 40% free space, up to the maximum allowed size of the generation. Similarly, if the free space exceeds 70%, then the generation will be contracted so that only 70% of the space is free, subject to the minimum size of the generation.

  6. After heap size setting parameters another option that affects GC performance is the proportion of the heap dedicated to the young generation. If you set the young generation to be bigger, minor collections will occur less often. But that would mean a smaller tenured generation, which will increase the frequency of major collections.

    Three options for tuning the young generation are -

  7. Task: Setting the Young generation heap size

    Option: -XX:NewSize

    It is recommended to set -XX:NewSize to be one-fourth the size of the heap size.

  8. Task: Set the maximum size of the Young Generation heap size.

    Option: -XX:MaxNewSize

  9. Task: Controlling the ratio between young and tenured generation

    Option: -XX:NewRatio

    As example if you set -XX:NewRatio=3 that would mean the ratio between the young and tenured generation is 1:3. The size of the eden + survivor spaces will be one-fourth of the total heap size.

  10. You can also tune the size of the survivor spaces, for that you can use the parameter SurvivorRatio.

  11. Task: Tune the size of the survivor spaces

    Option: -XX:SurvivorRatio

  12. As example if you set -XX:SurvivorRatio=6 that would mean the ratio between eden and a survivor space is 1:6. Which means each survivor space will be one-sixth the size of eden, thus one-eighth the size of the young generation.

Heap memory profiling

Though there are many tools available to profile the memory, I am mentioning one I have already used Java VisulalVM. It’s free and comes bundled with JDK itself. Another tool you will find in the same location is jconsole which is also a monitoring tool.

To launch you just need to go to bin directory of your installed JDK folder and launch jvisualvm from there.

On the left side pane it will show the running Java applications, just click on the one you want to inspect.

Here I am demonstrating its use with a very simple application where I have created a thread and in that thread I am creating 5000 objects of another class with some thread pause (by using sleep method) in between. For this program I changed the -Xms and -Xmx so that the heap is small.

First image shows the heap when the program is just started, that’s why you see a very little variance in the used heap.

Second image is a snapshot of the heap memory when garbage collection occurred that is why you can see a sudden dip in the used heap memory. If you see at 3:50 PM in the graph you will see a GC activity which has taken 1.3% of CPU time.

Third image also shows a GC activity. At 3:52 PM you can see a barely visible blue mark showing GC activity and a corresponding dip in the used heap memory.

So using VisualVM GUI tool you can monitor your application’s memory usage, also analyze process threads and get a thread dump. Also profile the performance of your application by analyzing CPU and memory usage.

That's all for this topic Heap Memory Allocation in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. JVM Run-Time Data Areas - Java Memory Allocation
  2. Just In Time Compiler (JIT) in Java
  3. What are JVM, JRE and JDK in Java
  4. How to run javap programmatically from Java Program
  5. How to pass command line arguments in Eclipse
  6. PermGen Space Removal in Java 8

You may also like -

>>>Go to Java advance topics page