Google

Oct 23, 2014

Debugging and working like a pro with a Java application tutorial with eclipse IDE

Often you get to work on a fully functional Java application that is already in production to fix production issues or to enhance its existing functionality. As a new Java developer in the team, it is not easy to get started and contributing. The approach would be slightly different from working on a brand new project. Here are a few tips that will help you hit the road running as quickly as possible.

This post will also help you answer a common developer interview question --

Q. How will you hit the road running fast on an enhancement or a bug fix task of a large  existing application with 1000+ artifacts?
A. Key terms are: Setting up the environment, familiarizing with the app, reverse engineering, impact analysis, monitoring the logs, and collaborating  with the team members and knowledge transferring.

Step #1: Firstly, you need to get the application running locally in your development environment. So, with the help of your existing team members and online documentation provided via the internal wiki or confluence page you need to set up your development environment to run the application.
  1. Get all the Java tools required like Java, Maven, eclipse IDE, Tomcat/JBoss Server, tex editor like Notepad++, ssh emulator like putty/cygwin/mobaXterm/MSYS, tortoise SVN, etc
  2. Set up your Java and Maven locally
  3. Checkout the relevant Java projects from a code repository like Subversion (aka SVN).
  4. Set up data sources, environment variables, and .properties files.
  5. Build and deploy the Java application locally in your machine.

Step #2: Run the application locally, and get a basic familiarity as to how to navigate through the application.  Focus on the functionality you will be working with.


Step #3: A level of reverse engineering will be required to navigate through the actual user interface and then drill down into the code that is responsible for the functionality you are focusing on foxing on enhancing. Here are the tips to do that.


Step #3.1: Run the application in debug mode by modifying the log4j config file. This will print more log info like class names, method names, and stored procedure names being executed while you perform the UI navigation. You can then check the log file to get a list of relevant class names, methods, stored procedures, etc.

Step #3.1.1: Once you have the relevant class and method details, you can

Start to work like an eclipse pro to navigate through code:

You can use CTRL+SHIFT+T to search for Java class files



You can use CTRL+SHIFT+R to search for any resource files like .properties, .xml (Spring context file), .sql files, etc



Once you are within a Java class files, you can search for a particular method with CTRL+O.



You can drill down into other classes with F3 and Ctrl + left mouse click. The CTRL+ mouse click is very powerful drill down from ClassA to ClassB method invocations.



Step #3.1.2: Once you have worked out which artifacts to be modified, it is essential to perform impact analysis as to who is using these artifacts and if your fixes or enhancements going to impact any other existing functionality.

Start to work like an eclipse pro to perform impact analysis:

Highlight either a class name or a method name and press CTRL+SHIFT+G to find out from which classes and methods it is used or referenced from.


You can also highlight the class and press CTRL+H to search both Java classes and non Java type files like Spring context files, properties files, etc. This will cast a wider search where you have a number of tabs like file, Java, JavaScript, etc to search from.



Step #3.2: As an alternative to running the application in debug mode, you can also pick some labels key text on the GUI, and then use CTRL+H and then select the "File Search" tab to search for the web resources like .jsp, ,html, .xml, etc that have that search text. You can then drill down the other artifacts from there.

Step #4: When you are ready to make the code changes you can use code assist short cut keys described in  top 10 eclipse short-cut keys every Java eclipse developer must know.


Step #5: If you can't remember these short-cut keys initially, all you have to remember is

CTRL+SHIFT+L once
CTRL+SHIFT+L twice  


While unscrambling the relationship between the software functionality and code, maintain a documentation and produce high level diagrams. For example:

CashUI.jsp --> CashController.java --> CashService.java --> CashDao.java --&gt  getAvailbleCash.sql

Obviously you need to collaborate with a number of different team members to pick their knowledge, but most often team members can;t spoon feed you, and you need to hit the road running fast. This requires both good technical know how and great soft skills to get the job done.

Labels: ,

Jul 18, 2014

Which Jar has a particular class? or from which jar a class was loaded? solving jar hell issues

The following 3 questions are frequently asked by Java developers as an industrial strength Java project will have 100+ jar files. How often have you come across a Java application that requires different versions of the same library? How often do you see exceptions like NoSuchMethodError or IllegalArgumentException. Here are some tips to solve the JAR hell problem. These 6 tips will go a long way in resolving your jar problems.

Q1. Which Jar has a particular class?

Tip#1: go to findJAR.com and search for the class file. For example, I want to find the jar file that has org.apache.commons.io.FileUtils



You can drill through to find a Maven download link.




Tip#2: Unix command "find" and grep

find ./lib -name "*.jar" -exec sh -c 'jar -tf {}|grep -H --label {} 'org.apache.commons.io.FileUtils'' \;




Tip#3: In Windows or DOS

 
for %i in (*.jar) do @jar tvf %i | find "org/apache/commons/io/FileUtils.class"



Q2. from which jar a class was loaded?

Tip#4. To identify from which jar a particular class was loaded from, add the following snippet of code to  a location where it gets executed.

   Class klass = org.apache.commons.io.FileUtils.class;

   CodeSource codeSource = klass.getProtectionDomain().getCodeSource();

    if ( codeSource != null) {
        System.out.println(codeSource.getLocation());
    }


At run time it will print the jar file from which "FileUtils" was loaded.

package test;

import java.security.CodeSource;

public class WhichJarLoadedTest {

 public static void main(String[] args) {
  Class klass = org.apache.commons.io.FileUtils.class;

  CodeSource codeSource = klass.getProtectionDomain().getCodeSource();

  if (codeSource != null) {
   System.out.println(codeSource.getLocation());
  }
 }

}


Output:

 file:/C:/Users/akumaras/workspace/WtsPlayProject/lib/commons-io-2.4.jar
 

 Q3. Why commons-io version 2.1 was chosen over version 2.4?


Tip #5: In Maven, due to its transitive dependencies behavior, multiple versions of same jar could be pulled in. You need to determine which jar is bringing in the this duplicate or wrong version of the jar and exclude it in the pom.xml file. The verbose flag instructs the dependency tree to display conflicting dependencies that were omitted from the resolved dependency tree. For example, to see why commons-io 2.0 was chosen over commons-io 2.4

  mvn dependency:tree -Dverbose -Dincludes=commons-io
  
The 3 handy commands to solve jar hell issues in maven are mvn dependency:tree, mvn dependency:analyze, and mvn help:effective-pom. The IDEs like eclipse provide tools to analyze dependencies. In eclipse, double click on a pom.xml file, and then select the "Dependency Hierachy" tab to analyze why a particular jar was chosen.

<dependency>
 <groupId>org.jboss.resteasy</groupId>
 <artifactId>resteasy-jaxrs</artifactId>
 <version>${resteasy.version}</version>
</dependency>



commons-io-1.4 is a very old version. Now to to exclude older version and include commons-io-2.4, you need to do the following in the pom.xml file.

  
<dependency>
 <groupId>org.jboss.resteasy</groupId>
 <artifactId>resteasy-jaxrs</artifactId>
 <version>${resteasy.version}</version>
 <exclusions>
      <exclusion>
          <groupId>commons-io</groupId>
          <artifactId>commons-io</artifactId>
      </exclusion>
 </exclusions> 
</dependency>
<dependency>
        <groupId>commons-io</groupId>
     <artifactId>commons-io</artifactId>
     <version>2.4</version>
</dependency>




Tip #6:  uber-jar is an "over-jar", and uber is the German word for above or over. uber-jar is defined as one that contains both your package and all its dependencies in one single JAR file (Note: jars cannot have other jars). The advantage is that you can distribute your uber-jar and not care at all whether or not dependencies are installed at the destination, as your uber-jar actually has no dependencies. Maven has a plugin known as the "Apache Maven Shade Plugin".

 This plugin can also be used in scenarios where you are using two jars X and Y. Y is a library and X has classes that uses some old classes from library Y with same names causing a jar hell issue.  You can solve your problem by renaming the package of the class that you don't want.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
            </goals>
        <configuration>
                <relocations>
                    <relocation>
                            <pattern>com.myapp.MyClass</pattern>
                               <shadedPattern>com.myapp.rename.MyClass</shadedPattern>
                    </relocation>
                </relocations>
                    <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
        </configuration>
        </execution>
    </executions>
</plugin>


Labels: ,

Jul 17, 2014

Top 5 tips for debugging Java thread-safety, multi-threading, or concurrency issues

Tutorial style debugging of Java thread safety issues extending general tips outlined in Identifying and fixing Java concurrency issues

#1: Manually reviewing the code for any obvious thread-safety issues. Good knowledge of multi-threading is required.

#2: List all possible causes and add extensive log statements and write test cases to prove or disprove your theories. The log statements will have something like

log.info(Thread.currentThread().getName() + " produced: " + count);
System.out.println(Thread.currentThread().getName() + " consumed: " + consumed);

#3: Using your IDE debugging capability by setting a conditional break point.  Thread.currentThread().getName().equals("Thread-0"). For example, stopping for particular thread as demonstrated below step by step in eclipse IDE. The working code can be found at Java producer consumer working example.




The above code continuously produces output like:

Thread-0 produced: 1
Thread-1 consumed: 1
Thread-0 produced: 2
Thread-1 consumed: 2
Thread-0 produced: 3
Thread-1 consumed: 3
Thread-0 produced: 4
Thread-1 consumed: 4


You can add a break point to the ProducerConsumer that is used by both worker threads ProducerThread and ConsumerThread. Both these worker threads are spawned by the default main thread.

Step 1: Create a conditional debug point as shown below in the first line of the produce method.



Step 2: Run the ProducerConsumerTest in debug mode. The execution stops on the break point when worker "Thread-0" enters the break point. In the above example only one thread enters produce( ) method. But in industrial applications you can have many threads.

You also have options to suspend and resume the threads you want as shown below with right-click context menu in the debug window. When you are suspended, you can also copy the stack at that suspended point in time.



You can also inspect and watch shared variables to ascertain any thread-safety issues.


The above diagram adds a watch expression on a shared variable.


#4: Thread dumps are very useful for diagnosing synchronization problems such as deadlocks. The trick is to take 5 or 6 sets of thread dumps at an interval of 5 seconds between each to have a log file that has 25 to 30 seconds worth of run-time action. For thread dumps, use kill -3 in Unix and CTRL+BREAK in Windows. There are tools like Thread Dump Analyzer (TDA), Samurai, etc. to derive useful information from the thread dumps to find where the problem is. For example, Samurai colors idle threads in grey, blocked threads in red, and running threads in green. You must pay more attention to those red threads.

Creating a thread dump in windows

Step 1: While the ProducerConsumerTest  is running, open a DOS command prompt at type jconsole.




Note down the process id: 4800. Connect to 4800, and 

Step 2: You can detect any deadlocks by clicking on the "Detect Deadlock" button in the threads tab.

Step 3: To get a thread dump, open a DOS command prompt and type jstat [pid]

jstat 4800

This will produce a stack trace. The stack trace looks something like



You need to pay attention to blocked threads, and there are tools like  Thread Dump Analyzer (TDA), Samurai, etc to analyze thread dumps.

jstack and jconsole are provided with your JDK installation under jdk[version]/bin.

#5: There are static analysis tools like Sonar, ThreadCheck, etc for catching concurrency bugs at compile-time by analyzing the byte code. Sonar produces reports with recommendations.

Labels: ,

Feb 27, 2014

Debugging Java Class loading issues

"I thought that I was using my application package version of a library but apparently my application server (e.g. Weblogic, JBoss) has already loaded an older version of this-library-issue" 

These issues normally arise when there are certain classes which are packaged along with Application Server as part of common libraries and the same set of classes are also present in your Application package as well (normally inside WEB-INF/lib folder of the application). The reasons for the problem lies with how the class loading works in any Application Server.

A common question many developers ask is that

Where on the file system was my Java class loaded from?

Here are some tips and steps to troubleshoot Java class loading issues.

1. -verbose:class option in your JVM. With the -verbose option all the classes that are loaded are listed, along with the JAR file or directory from which they were loaded. The "class" output shows additional information, such as when superclasses are being loaded, and when static initializers are being run.

2. Creating a Java dump and analyzing the Java dump for class loading issues. The Java dumps are created under following circumstances.
  • When a fatal native JVM error.
  • When the JVM runs out of heaps memory space.
  • When a signal is sent to the JVM (e.g. Control-Break is pressed on Windows, Control-\ on Linux, or kill -3 on Unix)
There are tools like jstack, jmap, hprof, and Eclipse Memory Analyzer (MAT) to analyze the Java dumps.

3.  Some of the libraries provide API to list the version number. For example, The Eclipse link MOXy library provides a method as shown below.

  PrintWriter out = response.getWriter();
  out.println("<html>");
  out.println("<body>");
  out.println("<h1>Simple</h1>");
  out.println(org.eclipse.persistence.Version.getVersion());
  out.println("</body>");
  out.println("</html>");
 

4.  The org.jboss.test.util.Debug class has a method  displayClassInfo(Class clazz, StringBuffer results) to display the loaded class details. This is done programmatically. What this class essentially does is

    


URL loc = MyClass.class.getProtectionDomain().getCodeSource().getLocation();


 

5. The http://www.findjar.com is an onlime search engine that can list possible jar files in which a particular class file like java.sql.Connection can be found.




6. Finally, using the Unix find and grep commands to list the jar files that has a given class file like "Connection".

 


find . -name '*.jar' -print0 |  xargs -0 -I '{}' sh -c 'jar tf {} | grep Connection.class &&  echo {}' 



You may also like

Labels: ,