Monday, September 27, 2010

Take a trip into Java Monitor with your source code






                      line 1:  synchronized(obj){//Entry Set
                      line 2:       System.out.println ("I am the master of monitor");//Owner
                      line 3:       obj.wait();//Wait Set
                                 }
                      line 4:           //Out of the monitor

More than one thread can be blocked/found on line 1 , line 3 and line 4 at the same time, but there can only be one active thread at the same time at line 2 as a monitor owner.

You may want to check this sample also : http://javabender.blogspot.com/2010/09/example-for-understanding-javas-wait.html

Thursday, September 23, 2010

Example for Understanding Java's Wait / Notify Mechanism and Synchronization

 public class WaitNotifyExample {

    public static void main (String[] args) {
        final Object obj = new Object();

        Runnable r = new Runnable () {
            public void run () {
                while (true) {
                    try {
                        System.out.println ("-- this lines are being printed in another thread.." + Thread.currentThread ().getName ());
                        synchronized(obj){// The current thread must own this object's monitor see javadoc guys..Object.wait ();
                            obj.wait();// just wait for somebody else to awake you here.
                        }
                    } catch (Exception ex) {
                        System.out.println (" -- Interrupted...");
                        ex.printStackTrace ();
                    }
                }
            }
        };

        new Thread (r).start ();//we crated and started a lazy guy here
        new Thread (r).start ();//another lazy guy
        new Thread (r).start ();//this can be me :)

        while (true) {
            System.out.println (" -- this lines are bing printed in main thread.." + Thread.currentThread ().getName ());
            try {

                Thread.currentThread ().sleep (5000);//Our master will sleep for 5 seconds
                synchronized(obj){//same reason with above synchronized
                    obj.notifyAll();// Then it will say others wake up !
                }
                Thread.currentThread ().sleep (500);//If we don'T stop the main thread here it will be the owner of the monitor of obj object always.
                                                    //It is in a while loop.Others will be blocked on synchronized statement.

            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
    }
}



---| Lets look at to the system out , I have took a thread dump for u also  |-----
-- this lines are being printed in another thread..Thread-0
-- this lines are being printed in another thread..Thread-1
 -- this lines are bing printed in main thread..main
-- this lines are being printed in another thread..Thread-2
-- this lines are being printed in another thread..Thread-0
-- this lines are being printed in another thread..Thread-1
 -- this lines are bing printed in main thread..main
-- this lines are being printed in another thread..Thread-2
-- this lines are being printed in another thread..Thread-0
-- this lines are being printed in another thread..Thread-1
Full thread dump Java HotSpot(TM) Server VM (1.5.0_08-b03 mixed mode):

"Thread-2" prio=1 tid=0x09dcaa88 nid=0xfa6 in Object.wait() [0x6e8cb000..0x6e8cc080]
    at java.lang.Object.wait(Native Method)
    - waiting on <0xaa00e258> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:474)
    at sil.WaitNotifyExample$1.run(WaitNotifyExample.java:17)//
obj.wait()
    - locked <0xaa00e258> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:595)

"Thread-1" prio=1 tid=0x09dc9218 nid=0xfa5 in Object.wait() [0x6e94c000..0x6e94d100]
    at java.lang.Object.wait(Native Method)
    - waiting on <0xaa00e258> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:474)
    at sil.WaitNotifyExample$1.run(WaitNotifyExample.java:17)//
obj.wait()
    - locked <0xaa00e258> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:595)

"Thread-0" prio=1 tid=0x09dcb550 nid=0xfa4 in Object.wait() [0x6e9cd000..0x6e9cdd80]
    at java.lang.Object.wait(Native Method)
    - waiting on <0xaa00e258> (a java.lang.Object)
    at java.lang.Object.wait(Object.java:474)
    at sil.WaitNotifyExample$1.run(WaitNotifyExample.java:17)//
obj.wait()
    - locked <0xaa00e258> (a java.lang.Object)
    at java.lang.Thread.run(Thread.java:595)

"main" prio=1 tid=0x09cecee0 nid=0xf94 waiting on condition [0xbfe77000..0xbfe776f8]
    at java.lang.Thread.sleep(Native Method)
    at sil.WaitNotifyExample.main(WaitNotifyExample.java:37)//
Thread.currentThread ().sleep (500)

Monday, September 6, 2010

How to debug our code on the remote machine : remote debugging with jbuilder and intellij idea..

We write our code in our pc then we put it to a remote server. Sometimes it fails :)
Then what do you do to understand what is going on ?
Thread dump does not give what you need.
You need to connect your java process and debug.


To debug a process which is running a remote server you need to start it with the following JVM_ARGs.


-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3999,suspend=n


Sample usage : java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3999,suspend=n com.mycompany.test.WriteYourOwnCode


By the way your process will be waiting your connection from your machine whenever you want. Port number [3999] will be reserved for this debugging connections. Try to reserve a port number which is not used any other process/system.Otherwise your process will not start.You will see an error in this case something like this.


[serkans@serkansunellnx voicemail] java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3999,suspend=n com.mycompany.test.WriteYourOwnCode
ERROR: transport error 202: bind failed: Address already in use ["transport.c",L41]
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510) ["debugInit.c",L500]
JDWP exit error JVMTI_ERROR_INTERNAL(113): No transports initializedFATAL ERROR in native method: JDWP No transports initialized, jvmtiError=JVMTI_ERROR_INTERNAL(113)


In the jvm_args you see an option : suspend=n . This means your remote code will not wait anybody to connect it before start. If you set this option to YES [suspend=y] process will wait before starting automatically. This suspend options must be set to YES [suspend=y] when you are unable to catch an error which is  happens in the beginnging of the process.


After starting our process with this options it is running and listenning for your connections...


Let me put a few picture to show how to connect to a remote process.
I'll show for both JBuilder and IntellijIdea.


1) Remote debugging with Jbuilder.


Firstly we start our code on a remote server with the remote debugging options.


[serkans@serkansunellnx voicemail] java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3999,suspend=n socketLogger.LogServer
Listening for transport dt_socket at address: 3999
 >> Server waiting for log messages...

It started and said that waiting on port 3999.It is not hanged.It is running, cool down :)



Then we turn to our ide.In the Jbuilder Right Click on the project and select project properties.
Click to the Run on the left pane of the project properties window.You will see RunTime Configurations. Click to New . A new window will appear called "New Runtime Configuration".Then click to the Remote in the left pane of this window.
1) Select "Enable Remote Debugging" by clicking the checkbox.
2) Select "Attach".
3) Write the IP of remote server on which your code is running as hostname.
4) Change the port number if you selected something different from 3999.


That is all.Click OK , OK  and close these windows.


It will looks like that :




After doing these right click on your Project .Select Debug..Ohh yes now you see the newly defined Runtime Configuration called "Your connection to remote process". Yes ...Click on this.




Now you are connected to your code.Go there and put your breakpoints. If your process hit your breakpoints you will notice it :-)


I got tired... I will expain it for Intellij Idea later.

Simple Log server with java SocketHandler and centralization of log records

A common requirement for all enterprise systems is the centralization of log records.

This systems simply use the SocketHandlers to store/display ongoing event logs.

SocketHandler is a subclasses of StreamHandler. Others classes are consoleHandler, FileHandler and SocketHandler.

In a distributed system nobody can perform a healty monitoring activity on the whole system without a centraliazed log system.

Let's have look at SocketHandler.

The following class will produce logs and sent to LogServer.

package socketLogger;

import java.io.*;
import java.util.logging.*;

public class LogTest {
    private static Logger logger = Logger.getAnonymousLogger ();
   
    public static void main (String argv[]) throws IOException {
        Handler handler = new SocketHandler ("localhost", 5000);
        //set handler log level
        handler.setLevel (Level.FINEST);
        //set logger log level
        logger.setLevel(Level.FINEST);
        //add socket handler to sent our logs to log server..
        logger.addHandler (handler);

        //lets make some noice
        logger.log (Level.SEVERE, "Hello, World");
        logger.log (Level.INFO, "Welcome Home");
        logger.log (Level.CONFIG, "Config ....");
        logger.log (Level.FINE, "Fine ....");
        logger.log (Level.FINEST, "Finest ....");
        logger.log (Level.WARNING, "Warning ....");
    }
}


And our log server which listens incoming logs and prints them to console.You can build your own log server with a nice gui and filtering/searching capabilities by enhancing this.

package socketLogger;

import javax.net.ssl.*;
import javax.net.*;
import java.io.*;
import java.net.*;

public class LogServer {
    private static final int PORT_NUM = 5000;
    private static ServerSocket serverSocket;
   
    public static void main (String args[]) {
        serverSocket = createServerSocket ();
        listenAndPrintLogMessages ();
    }

    private static void listenAndPrintLogMessages () {
        while (true) {
            Socket socket = null;
            try {
                System.out.println (" >> Server waiting for log messages...");
                socket = serverSocket.accept ();

                InputStream is = socket.getInputStream ();
                BufferedReader br = new BufferedReader (new InputStreamReader (is, "US-ASCII"));
                String line = null;
                while ((line = br.readLine ()) != null) {
                    System.out.println (line);
                }
            } catch (Exception e) {
                e.printStackTrace ();
            } finally {
                if (socket != null) {
                    try {
                        socket.close ();
                    } catch (IOException ignored) {
                    }
                }
            }
        }
    }

    private static ServerSocket createServerSocket () {
        ServerSocketFactory serverSocketFactory = ServerSocketFactory.getDefault ();
        try {
            serverSocket = serverSocketFactory.createServerSocket (PORT_NUM);
        } catch (IOException ioEx) {
            System.err.println ("Unable to create server");
            ioEx.printStackTrace();
            System.exit ( -1);
        }
        return serverSocket;
    }
}

see in action


And here is our logs which is captured from ServerSocket and printed to console in. By default the XMLFormatter class is used for formatting in the socket handler.So we have very nice log records now :)

 >> Server waiting for log messages...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2010-09-06T23:01:02</date>
  <millis>1283803262382</millis>
  <sequence>0</sequence>
  <level>SEVERE</level>
  <class>socketLogger.LogTest</class>
  <method>main</method>
  <thread>10</thread>
  <message>Hello, World</message>
</record>
<record>
  <date>2010-09-06T23:01:03</date>
  <millis>1283803263161</millis>
  <sequence>1</sequence>
  <level>INFO</level>
  <class>socketLogger.LogTest</class>
  <method>main</method>
  <thread>10</thread>
  <message>Welcome Home</message>
</record>
<record>
  <date>2010-09-06T23:01:03</date>
  <millis>1283803263162</millis>
  <sequence>2</sequence>
  <level>CONFIG</level>
  <class>socketLogger.LogTest</class>
  <method>main</method>
  <thread>10</thread>
  <message>Config ....</message>
</record>
<record>
  <date>2010-09-06T23:01:03</date>
  <millis>1283803263162</millis>
  <sequence>3</sequence>
  <level>FINE</level>
  <class>socketLogger.LogTest</class>
  <method>main</method>
  <thread>10</thread>
  <message>Fine ....</message>
</record>
<record>
  <date>2010-09-06T23:01:03</date>
  <millis>1283803263172</millis>
  <sequence>4</sequence>
  <level>FINEST</level>
  <class>socketLogger.LogTest</class>
  <method>main</method>
  <thread>10</thread>
  <message>Finest ....</message>
</record>
<record>
  <date>2010-09-06T23:01:03</date>
  <millis>1283803263172</millis>
  <sequence>5</sequence>
  <level>WARNING</level>
  <class>socketLogger.LogTest</class>
  <method>main</method>
  <thread>10</thread>
  <message>Warning ....</message>
</record>
 >> Server waiting for log messages...

About JVM Options

  • Options that begin with -X are non-standard (not guaranteed to be supported on all VM implementations), and are subject to change without notice in subsequent releases of the JDK.
  • Options that are specified with -XX are not stable and are not recommended for casual use. These options are subject to change without notice. 
Don't expect to see abnormal tps increasement by using an option something like [-XX:+StringCache] this is why i am telling this here.

-XX:+StringCache : Enables caching of commonly allocated strings.

But it would be GREET :) if works huh ?