Sunday, August 14, 2016

Oracle VM


Virtualization is a technique to share the hardware resources among multiple systems or users to achieve optimal usage of resources and reducing costs.

Although virtualization is a generic one conceptually, lets talk on server virtualization. This means a bunch of HW resources like CPUs, Memory, Disks, ports etc., are shared among multiple OSs either of same type or multiple type. So, to achieve this we need someone or something to manage the underlying HW and above running guests (OSs). This 'manager' is what is called a 'Hypervisor'.

There are couple of types of Hypervisors
Native or bare metal hypervisor - this is the software which directly runs on host's hardware to control the hardware and monitor the guests OS. so imagine this something that mediates between guest OS and underlying hardware. Example of
such implementation are Oracle VM, VMware EXXi Xen, Microsoft Hyper-V

The other hypervisor is made to run within a traditional operating system and then guest OSs can run on top of it. Example Oracle VirtualBox (which can be installed on an PC where windows is the base OS but virtual box can then host another guest OS like linux..


Oracle VM Server:

This can be installed on X86 instruction set based platforms with Xen hypervisor (GPU licensed) or on SPARC platforms (which will have its own hypervisor).
In general, the above implementation has their own firmware/hardware, a hypervisor and then a super domain/vm which controls the resource allocation to other guest VMs (also called domains or simply guests)

So, simply Oracle VM server is a collection of hardware (CPU, Mem, Network, IO etc.,), hypervisor (for managing underlying baremetal i.e. the hardware), domains (the VMs with thier own set of OS except Dom0 which a complete linux kernel and manages all the other Domains).

Lets explore some interesting things related to Oracle VM

CPU capacity:
how to determine the cpu capacity on a vm server
xm info is the command to use. for example, as shown below, the number of cpus are 72 which are ideally the threads. There are 2 nodes, 18 cores per socket and 2 threads per core
i.e. 2 * 2 * 18 = 72 threads (0 to 71 total, 0-35 on sock1, 36-71 on sock2)

nr_cpus                : 72
nr_nodes               : 2
cores_per_socket       : 18
threads_per_core       : 2

The cpu topology can be viewed by using the commnad xenpm get-cpu-topology
CPU     core    socket  node
CPU0     0       0       0
CPU1     0       0       0
CPU2     1       0       0
CPU3     1       0       0
..
xm info also gives the high level vm details like what bit it supports, what instruction set (like intel x86), number of real cpus, number of nodes, number of sockets, number of threads per core, cpu frequency,
memory, pagesize etc.,
In an hyperthreaded model, each core will run 2 threads instead of one. and this would have counter effects but could improve efficiency..


vCPUs
virtual cpus are the cpus that are assigned to a guest/domu i.e. a virtual machine which runs on a domu can be assigned 10 CPUs which are considered as virtual cpus and the actual bindings to real cpu depends on how they are configured. For example below, vm1 is a virtual machine with the id=1, has 3 vCPUs which are in bind state and mapped to CPUs 3,6 7. This vm1 is configured to have the cpu affinity as 2-35 which is first socket on a 2 socket 72 core machine. so, since there is no absolute binding, the mapping can change in runtime and depends on the availability,
the vcpus can be mapped to any of the real cpus in the range 2-35.

xm vcpu-list
Name  ID  VCPU   CPU State   Time(s) CPU Affinity
vm1   1     0     3   -b-   5354.1 2-35
vm1   1     1     6   -b-   2312.4 2-35
vm1   1     2     7   -b-   2337.8 2-35

you can pin the CPUs for guest vms runtime but to change any affinity to dom0 requires a reboot.. and dom0 always takes the top priority.
And, it is always good to monitor the real cpu usage from the vm server to check how in an  oversubscribed case, the busy vms on the same socket could impact each other..

JNDI - Java Naming and Directory Interface




JNDI - Java Naming and Directory Interface

what is JNDI - its a naming service
why is it needed - in a distributed enterprise application, there are multiple resources like DB pools or business components like EJBs deployed on the Java EE containers and they need a way to locate. JNDI serves that purpose.

Applications can use annotations to locate the resource. Like datasources which are nothing but database resources, provides connection to database. when the application code refers to a
 datasource and invokes JDBC API to getconnection, it gets a physical connection. In case connection pooling is implemented then it gets a handle to pooled connection object instead of direct physical connection.
 These connections need to be closed and when closed will go back to the pool. The pool of database connections will give better performance and better connection handling mechanism.

Similarly JNDI mapping can be done to other services like JMS, LDAP etc.,

Below shown are some of the resources on Glassfish server and the JNDI mapping.








Monday, August 8, 2016

Oracle database performance


Lets explore Oracle database performance aspects on a high level..

some of the key terms to know about:

SGA: Shared Global Area - is basically a collection of memory units or structures used by all the processes on a db instance.
PGA: Program Global Area- is a memory region specific to a process (server process or bg process).
Buffer Cache: is basically a buffer to keep data blocks read from data files. The buffer cache is shared across the users.
Shared pool: basically contains the program data like parsed SQLs, PL/SQL code, data dictionaries etc., and this is accessed almost in every DB operation.

And lets see some of the interesting views
gv$process contains details on the currently active processes which are either on CPU or on latchwait or in spinning on a latch.. also contains PGA details for this process
gv$sgastat contains details on the system global area (SGA). For each pool - shared/large/java/stream pools
gv$session contains details for each current session. data from this view is sampled every sec and put into V$ACTIVE_SESSION_HISTORY. From 11G Rel 2 onwards, each individual req can be traced with the help of ECID.
gv$pgastat contains details on PGA usage

we can take a periodic snapshots on the above tables to analyze further..
example: CREATE SNAPSHOT snapshotonprocess AS SELECT * FROM gv$process
and then the processes pga can be calculated.. like select inst_id, count(*) cnt, Round(sum(PGA_USED_MEM) / 1024 / 1024 / 1024, 2) from snapshotonprocess group by inst_id order by inst_id
- adding a criteria like 'background is not null' will give pga stats for background processes

similarly, we can query sga stats, shared pools, shared pool usage, buffer cache usage and active sessions etc.,

Another good place to look at for session performance and to point out the slow SQLs or event waits is by querying V$ACTIVE_SESSION_HISTORY.
V$ACTIVE_SESSION_HISTORY contains sampled session activity in the database. samples are taken every sec. So, it is possible to calculate howmuch time spent on DB  and on which queries for a end user request by tracing the ECIDs in this view.

Lets look at awesome reports by Oracle database on performance of the database.

AWRs- A great performance report on DB workloads. It contains information about DB time, system resource usage, waits or other events that could impact performance, SQL statistics like long running SQLs or resource intensive sqls or
SQLs with high buffer gets.
we can check how the buffer cache and shared pool size changed from the beginning to the end of the snapshots.
logical reads(the more the better), physical reads(the less the better), hardparses(the more over a warmedup system indicates the plans are not good perhaps and might need to gather stats or something attached to the queries in runtime), rollbacks etc.,
latches(a short lived serialization methods that oracle uses on shared structures) efficiency metrics, top 5 foreground events, CPU and memory stats are good place to start with if there is a overall db performance hit.
If the performance is specific to SQLs then other areas to look at in AWRs are related SQL performance - # of execs, time taken per exec, cpu used, buffer gets, hard parses etc., And, up on identifying the SQLs (best way is to match the ECIDs for the frontend initiated SQLs),
SQLHC is next step to analyze further on the historical performance and the to analyze the SQL execution plan, indexes, bind variables/conditions etc.,

To have a better insight, keep a good baseline AWR in the system so that any future snapshot can be compared against it..

To create a awr snap:
EXEC DBMS_WORKLOAD_REPOSITORY.create_snapshot;
select snap_id from dba_hist_snapshot order by snap_id asc;

To generate AWR: select output from table(dbms_workload_repository.awr_report_html(,,,));

To declare the basline:
BEGIN   DBMS_WORKLOAD_REPOSITORY.create_baseline (     start_snap_id => <###>,     end_snap_id   => <###>,   baseline_name => 'baseline'); END;
 /

To compare AWRs:
@$ORACLE_HOME/rdbms/admin/awrddrpi.sql
or
select * from TABLE(DBMS_WORKLOAD_REPOSITORY.awr_diff_report_html(,,,,,,,));


Other good reports to look at:
ADDM report - an Automatic Db Disgnostic Monitoring report.. helps identifying the issues in an Active Workload Repository

Saturday, July 16, 2016

Weblogic MBean Monitoring


Weblogic provides a nice feature to monitor the server resources i.e. through MBeans.

weblogic mbeans types - configuration MBeans, Runtime MBeans and Application Defined MBeans

These can be browsed from EM console - go to admin server EM url for the domain which you are interested. Navigate to the server under the domain from EM console and then menu - System MBean Browser

you can see the above 3 types of MBeans tree structure. Normally for runtime stats, we check Runtime MBeans. say  com.bea - select a server - ServerRuntime - and select a type of MBean to browse and select the server


Example MBean for JDBC Data Sources

MBean Name com.bea:ServerRuntime=Server_1,Name=Server_1,Location=Server_1,Type=JDBCServiceRuntime
There are many attributes for this MBean and interesting one to monitor the resource usage is 'JDBCDataSourceRuntimeMBeans'
This attribute will list all the data sources configured for the server - click on a datasource to see its current usage

This is same as what we monitor from Admin console - datasources - monitoring ..

The same can also be done via a script using python/wlst

------------------------------------------------------------------------------------
def getConnectionPoolStat():
connect('adminUserName', 'adminPassword', 'adminURL')
name=cmo.getName()
domainRuntime()
cd('ServerRuntimes')
srvrs=domainRuntimeService.getServerRuntimes()
crntdr=pwd()
for srv in srvrs:
srvName=srv.getName()
cd(crntdr)
print srvName
cd(srvName +'/JDBCServiceRuntime/' + srvName)
allDS=cmo.getJDBCDataSourceRuntimeMBeans()
cd('JDBCDataSourceRuntimeMBeans')
for ds in  allDS:
dsName = ds.getName()
cd(dsName)
lcc=cmo.getLeakedConnectionCount()
ccy=cmo.getCurrCapacity()
accc=cmo.getActiveConnectionsCurrentCount()
frrc=cmo.getFailedReserveRequestCount()
ctc=cmo.getConnectionsTotalCount()
acavg=cmo.getActiveConnectionsAverageCount()
cchc=cmo.getCurrCapacityHighCount()
achc=cmo.getActiveConnectionsHighCount()
ftrc=cmo.getFailuresToReconnectCount()
st=name + ',' + dsName + ',' + srvName + ',' + str(acavg) + ',' + str(accc) + ',' + str(achc) + ',' + str(ctc) + ',' + str(ccy)+','+str(cchc)+ ',' + str(lcc) +',' + str(frrc)+','+ str(ftrc) + '\n'
fo.write(st)
cd('..')


fo=open("outputcsvfile","w+")
fo.write('DomainName , DataSourceName, ServerName, Active Connections Avg Count, Active connections current count, Active Connections high count, Connections Total Count, Current Capacity , Current High Capacity, Leaked Connection Count, Failed ReserveRequest Count, FailuresToReconnectCount  \n')
getConnectionPoolStat()
fo.close()

This needs to be executed from wlst in oracle common home
sessions per app can be collected through weblogic_j2eeserver:app_session..





Friday, December 11, 2015

Java Web Services



Web services - in my simplistic view, these are the software components exposed over web (HTTP) as a service so various other programs or software modules can be able to interact. For easier understanding purpose, it is similar to how a web application deployed on an application server exposes its functions through a UI that a client program like internet browsers can access and display it. Web service even though communicate over HTTP, the exchange of information happens in an XML document with certain rules - called as SOAP (Simple Object Access Protocol)

Java provides an API to develop these components. This is called JAX-WS (Java API for XML Web Services).
And these can be implemented in 2 ways - RPC (remote procedure call) and in a message oriented i.e. in a document style

As this API makes it so simple, we just need below components to develop a simple webservice using JAX-WS

Lets see an RPC style implementation

1. Need a remote i.e. endpoint interface class
2. A remote implementation class
3. A remote publisher class
4. And a client

Below is the self explainable simple code logic

----------------
package com.myWSPackage;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.RPC)
public interface IamJustAnInterface{
@WebMethod String implementMe(String name);
}
----------------
package com.myWSPackage;
import javax.jws.WebService;

@WebService(endpointInterface = "com.myWSPackage.IamJustAnInterface")
public class IamAnImplementer implements IamJustAnInterface{
@Override
public String implementMe(String name) {
try{Thread.sleep(10000);}catch(Exception e){}
return "Hi There - at your service : " + name;
}
}
-------------------
package com.myWSPackage;
import javax.xml.ws.Endpoint;

public class IamAPublisher{

public static void main(String[] args) {
  Endpoint.publish("http://localhost:7777/ws/hi", new IamAnImplementer());
    }
}
---------------
package com.myWSPackage;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

public class WSClient{
  public static void main(String[] args) throws Exception {
  URL url = new URL("http://localhost:7777/ws/hi?wsdl");
    QName qname = new QName("http://myWSPackage.com/", "IamAnImplementerService");
    Service service = Service.create(url, qname);
    IamJustAnInterface ifi = service.getPort(IamJustAnInterface.class);
    System.out.println(ifi.implementMe("Buddy"));
    }
}
---------------------------------------------------

what happens on the client:
I have intentionally put a sleep in the service interface implementation class to capture the stacks

    SocketNativeIO.readBytesPinned(FileDescriptor, byte[], int, int, int)
    SocketNativeIO.socketRead(FileDescriptor, byte[], int, int, int) line: 32
    SocketInputStream.socketRead0(FileDescriptor, byte[], int, int, int)
    SocketInputStream.read(byte[], int, int) line: 129
    BufferedInputStream.fill() line: 218
    BufferedInputStream.read1(byte[], int, int) line: 258
    BufferedInputStream.read(byte[], int, int) line: 317
    HttpClient.parseHTTPHeader(MessageHeader, ProgressSource, HttpURLConnection) line: 690
    HttpClient.parseHTTP(MessageHeader, ProgressSource, HttpURLConnection) line: 633
    HttpURLConnection.getInputStream() line: 1195
    HttpURLConnection.getResponseCode() line: 379
    HttpClientTransport.readResponseCodeAndMessage() line: 198
    HttpTransportPipe.process(Packet) line: 151
    HttpTransportPipe.processRequest(Packet) line: 83
    DeferredTransportPipe.processRequest(Packet) line: 78
    Fiber.__doRun(Tube) line: 587
    Fiber._doRun(Tube) line: 546
    Fiber.doRun(Tube) line: 531
    Fiber.runSync(Tube, Packet) line: 428
    Stub.process(Packet, RequestContext, ResponseContextReceiver) line: 211
    SEIStub.doProcess(Packet, RequestContext, ResponseContextReceiver) line: 124
    SyncMethodHandler.invoke(Object, Object[], RequestContext, ResponseContextReceiver) line: 98
    SyncMethodHandler.invoke(Object, Object[]) line: 78
    SEIStub.invoke(Object, Method, Object[]) line: 107 ----> proxy and stub creation has been taken care by JDK
    $Proxy19.implementMe(String) ---------> is the remote call to the webservice's method
    WSClient.main(String[]) line: 15 ---------> is our client main method


what happens on the server side


    Thread.sleep(long) ------> just sleeps for 10 sec before it sends out the response
    IamAnImplementer.implementMe(String) line: 11 ---> call to the interface method which was exposed as a service
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[])
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25
    Method.invoke(Object, Object[]) line: 597
    InstanceResolver$1.invoke(Packet, Method, Object[]) line: 235
    InvokerTube$2.invoke(Packet, Method, Object[]) line: 135
    EndpointMethodHandler.invoke(Packet) line: 246
    SEIInvokerTube.processRequest(Packet) line: 82
    Fiber.__doRun(Tube) line: 587
    Fiber._doRun(Tube) line: 546
    Fiber.doRun(Tube) line: 531
    Fiber.runSync(Tube, Packet) line: 428
    WSEndpointImpl$2.process(Packet, WebServiceContextDelegate, TransportBackChannel) line: 232
    HttpAdapter$HttpToolkit.handle(WSHTTPConnection) line: 460
    HttpAdapter.handle(WSHTTPConnection) line: 233
    WSHttpHandler.handleExchange(HttpExchange) line: 95
    WSHttpHandler.handle(HttpExchange) line: 80
    Filter$Chain.doFilter(HttpExchange) line: 65
    AuthFilter.doFilter(HttpExchange, Filter$Chain) line: 65
    Filter$Chain.doFilter(HttpExchange) line: 68
    ServerImpl$Exchange$LinkHandler.handle(HttpExchange) line: 557
    Filter$Chain.doFilter(HttpExchange) line: 65
    ServerImpl$Exchange.run() line: 529
    ThreadPoolExecutor$Worker.runTask(Runnable) line: 886
    ThreadPoolExecutor$Worker.run() line: 908
    Thread.run() line: 662 ----> the publisher start a thread starts


The document style implementation is all the same way as above except the style declared in the remote
interface class will change to DOCUMENT.

The WSDL will be different for each of these implementations although there seems to be no change in the execution path i.e. stack traces shown above.

In Java EE7, there is support to implement RESTful webservices through the API called JAX-RS.
These are best suited when there is no need for state maintenance, can rely on underlying server caching mechanism and the content will not change dynamically and for light weight message exchanges like handsets, portable communication devices etc,. The RESTful services do not require XML messages or WSDL based API implementations.. They depend/implement the REST verbs like PUT/GET/POST/DELETE.. the implementation is very simple - a root reosource class annotated with the @PATH tells where the implemented java class is located and its methods annotated with the verbs like @GET, @Producer etc., tells which type of request handling will be done, what kind of text will be produced and the output etc., the servlet mapping defined the application's web.xml will tell the resource path and the mapped classes ro invoke.






Wednesday, November 25, 2015

Java String, StringBuilder and StringBuffer


What is so different between String, StringBuffer, StringBuilder ?

Strings are simple, constant size and represents a series of characters.
Since they are constants, strings can not be changed and you can simply exchange them.
StringBuilders make them a bit flexible and changeable. While StringBuilder and StringBuffer provides some similar features, StringBuffer is better when it is multi-threaded usage as the methods are synchronized.

A simple example:

public class StringAndStringBuilder {
    public static void changeString(StringBuilder sb){
        sb.delete(0, sb.length());
        sb.append("changed");
    }
public static void changeString(String s){
s="changed";

    }


    public static void main(String[] args) {
        StringBuilder sb=new StringBuilder("nothing");
        changeString(sb);
        System.out.println("value after change via stringbuilder "+ sb);
String s = new String("nothing");
changeString(s);
System.out.println("value after change via string "+ s);

    }
}
output:
value after change via stringbuilder changed
value after change via string nothing

Java Synchronization



Lets see how synchronization works in Java. Below is a sample program which has three parts
- TestSynchronization is a the main class
- TestThread is a private class extends Thread.
- IamSynchronized is one more private class which has synchronized code logic. one part is just a synchronous block and the other is a synchronous method.


public class TestSynchronization {
   public static void main(String args[]) {

      IamSynchronized IS = new IamSynchronized();
      TestThread T1 = new TestThread( "Thread - 1 ", IS );
      TestThread T2 = new TestThread( "Thread - 2 ", IS );
try{Thread.sleep(60000);}catch(Exception e){}
      T1.start();
      T2.start();
   }
}

class TestThread extends Thread {
   private Thread t;
   private String threadName;
   IamSynchronized IS ;
   TestThread(String name, IamSynchronized is){
       threadName = name;
       IS = is;
   }
   public void run() {
     IS.justIterate();
System.out.println("calling sync method - Thread: "+threadName);
IS.syncMethod();
     System.out.println("Thread " +threadName + " done");
   }

   public void start ()
   {
      System.out.println("Starting " +  threadName );
      if (t == null)
      { t = new Thread (this, threadName);
         t.start ();
      }
   }

}

class IamSynchronized {
   public void justIterate(){
    synchronized(this){
try {
         for(int i = 5; i > 0; i--) {
            System.out.println("Iteration --   "  + i );
Thread.sleep(1000);
         }} catch (Exception e) {    System.out.println("Interrupted"+e);  }
}
   }
   public synchronized void syncMethod(){
    {
try {
         for(int i = 5; i > 0; i--) {
            System.out.println("Iteration --   "  + i );
Thread.sleep(1000);
         }
     } catch (Exception e) {
         System.out.println("Interrupted"+e);
     }
   }
}
}

Lets see how the locking works and how the control flow happens when 2 parallel threads trying to execute the same logic.

Starting Thread - 1
Starting Thread - 2
I am in the non synchronous part of justIterate method - Thread Thread - 1
I am Thread Thread - 1  in sync block Iteration --   5
I am in the non synchronous part of justIterate method - Thread Thread - 2        -- THREAD 2 IS BLOCKED BY THREAD1
I am Thread Thread - 1  in sync block Iteration --   4
I am Thread Thread - 1  in sync block Iteration --   3
I am Thread Thread - 1  in sync block Iteration --   2
I am Thread Thread - 1  in sync block Iteration --   1
I am Thread Thread - 2  in sync block Iteration --   5
calling sync method - Thread: Thread - 1  -- THREAD 1 IS BLOCKED BY THREAD2
I am Thread Thread - 2  in sync block Iteration --   4
I am Thread Thread - 2  in sync block Iteration --   3
I am Thread Thread - 2  in sync block Iteration --   2
I am Thread Thread - 2  in sync block Iteration --   1
calling sync method - Thread: Thread - 2  -- THREAD 2 IS AGAIN BLOCKED BY THREAD1 BUT IN SYNC MTHOD
I am Thread Thread - 1  in sync method Iteration --   10
I am Thread Thread - 1  in sync method Iteration --   9
I am Thread Thread - 1  in sync method Iteration --   8
I am Thread Thread - 1  in sync method Iteration --   7
I am Thread Thread - 1  in sync method Iteration --   6
Thread Thread - 1  done
I am Thread Thread - 2  in sync method Iteration --   10  -- SINCE THREAD1 RELEASES LOCK, THREAD2 CONTINUES
I am Thread Thread - 2  in sync method Iteration --   9
I am Thread Thread - 2  in sync method Iteration --   8
I am Thread Thread - 2  in sync method Iteration --   7
I am Thread Thread - 2  in sync method Iteration --   6
Thread Thread - 2  done


Below stack trace gives an idea on how the locks being handled by the JVM


"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting for monitor entry [0x000000000d48f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at IamSynchronized.justIterate(TestSynchronization.java:47)
        - waiting to lock <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:24)
        at java.lang.Thread.run(Thread.java:722)

"Thread - 1 " prio=6 tid=0x000000000b550000 nid=0x18c4 waiting on condition [0x000000000d17f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.justIterate(TestSynchronization.java:49)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:24)
        at java.lang.Thread.run(Thread.java:722)

--------------------------------------------------

"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting on condition [0x000000000d48f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.justIterate(TestSynchronization.java:49)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:24)
        at java.lang.Thread.run(Thread.java:722)

"Thread - 1 " prio=6 tid=0x000000000b550000 nid=0x18c4 waiting for monitor entry [0x000000000d17f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at IamSynchronized.syncMethod(TestSynchronization.java:56)
        - waiting to lock <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)

--------------------------------------------------

"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting for monitor entry [0x000000000d48f000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at IamSynchronized.syncMethod(TestSynchronization.java:56)
        - waiting to lock <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)

"Thread - 1 " prio=6 tid=0x000000000b550000 nid=0x18c4 waiting on condition [0x000000000d17f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.syncMethod(TestSynchronization.java:58)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)

--------------------------------------------------

"Thread - 2 " prio=6 tid=0x000000000b550800 nid=0x2478 waiting on condition [0x000000000d48f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at IamSynchronized.syncMethod(TestSynchronization.java:58)
        - locked <0x00000007d5fbab18> (a IamSynchronized)
        at TestThread.run(TestSynchronization.java:26)
        at java.lang.Thread.run(Thread.java:722)