Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, June 24, 2008

Java One Liner - Reading a Text File at Once

Java is not meant or known for any one-liners, but who said we can't try? There you go:
String contents = new Scanner(new File("filepath")).findWithinHorizon(Pattern.compile(".*", Pattern.DOTALL), 0);

Cool, eh?

Hmm, may be not. Of course, you still have to deal with the checked exceptions + 3 import statements, etc. The so called one-liner by me has 113 characters (could be more or could be less if you consider the file path's length). I'm not sure if I would consider anything more than 80 chars as "one-liner" but hey, this is Java and this is as close as you can get.

Just for fun. Do you have anything better than this in Java? How about in Java 1.4? Now, don't write a separate method, call it, and say it's a one-liner for Perl sakes!

Thursday, April 24, 2008

How to Debug a Remote Java Application?

A Little Story

<skippable-story>
Recently I was working with a Java application that was bugging me when it was running in another country (USA) but it works fine when I run it on my desktop here in India. Of course, there is no connection with the geography except that the connection is slower. Every time I had a problem which is time consuming to reproduce on my desktop, I would login to that computer remotely through VNC client, reproduce the problem, get the logs, diagnose, and test it again there. You may ask, "Why don't you create a similar setup of that remote machine next to your desktop?" Trust me, there's a reason why I can't do it and I won't have a setup anytime sooner. Don't let that distract you about what I am trying to say, just forget it and assume I have to test it on a remote machine that resides in the same Intranet.

I was a having a conversation with one of my coworkers on phone about a particular problem and he said, "It will be slow but why don't you debug and see it?" My face turned red and I felt a little ashamed, I knew what he was talking about. He is a smart guy, I knew for sure he was not asking me to switch my whole development environment to some remote machine sitting on the other side of the globe. I hung up the phone, I walked to his desk and asked him. "Did you say debug?" He generously showed me how to do it. In fact, he thought that I don't know what is debugging and he explained me everything -- all that Step-Into, Step-Over, Step-Out stuff with its shortcuts.

It was easy for me to jump and say, "Dude! I know how to debug" but that would have been a wrong thing to do at that time. I know many people who come for help to me do this. So I quietly listened to him and gently said, "Yep, I'm familiar with that."

In case you have never done this before --here is how you do it. I will show how to do this using the Eclipse IDE, and I am very sure you are smart enough to figure out for your development setup.
</skippable-story>

Let's say you have your application compiled into a jar called myapp.jar and this will be running remotely on a machine called myremote.mycompany.com (or some IP). Your development machine is mydevel.mycompany.com. Now to debug the myapp.jar that is running remotely from your desktop machine, there are two steps you have to follow:
  1. Start the application and tell the JVM that it will be debugged remotely
  2. Configure your IDE on your desktop to be able to debug that remote application
Starting the Application with Remote Debugging Enabled

java -Xdebug -Xrunjdwp:transport=dt_socket,address=8998,server=y -jar myapp.jar
The above command says: start myapp.jar + start a server socket at port 8998 and publish the debugging messages using the Java Debug Wire Protocol (jdwp) there.

Other than address, server, and transport there are other sub options available for -Xrunjdwp option -- for example: suspend. I will leave that for you. Let's move on to step 2, that is configuring Eclipse.

Configuring Eclipse to Debug a Remotely Running Application

I will just show the screenshots without writing much, it's just intuitive that way.

1. Start Eclipse
2. Go to Run -> Debug Configurations



3. Create a new Remote Java Application configuration



4. Configure the remote application's details




5. If you would like to have this launch configuration in your favorites menu



6. Don't forget to click Apply

That it. Happy remote debugging!

Friday, February 29, 2008

The Deadly Question!

One of my favorite questions that I ask during an interview is "What is a deadlock and how do you avoid them?"

Typical answers:

Definition: Deadlock happens when Object 1 is waiting for Object 2 which is waiting for Object 1 again.

Avoiding deadlocks: (Answer 1): Using wait & notify. (Answer 2): Using synchronization.

Not only is the terminology wrong, it also clearly shows that the candidate is not sure with the fundamentals of multi-threading. To be frank, I was asked the same question when I was interviewed and I wasn't able to give a proper answer even though I did good amount of multi-threading before to answer this innocent looking question.

Lets suppose there are two threads T1, and T2 running in your application. T1 is executing a method called method1() and T2 is executing method2(). method1() has acquired lock1 and now it is trying to acquire lock2. But at the same time, method2() has acquired lock2 and it is now trying to acquire lock1. method1() cannot relinquish lock1 until it gets lock2 and finishes the job; method2() cannot relinquish lock2 until it gets lock1 and finishes the job. Both the threads, T1 and T2, are now waiting for one another to proceed their execution which will never happen. This situation is called a deadlock or a deadly embrace.

See the following code that is almost sure to encounter a deadlock during it's execution.
public class DeadLockDemo {
private Object lock1 = new Object();
private Object lock2 = new Object();

public void method1() {
while (true) {
// Acquire lock1 first
synchronized (lock1) {
// Acquire lock2 next
synchronized (lock2) {
System.out.println("Method 1");
}
}
}
}

public void method2() {
while (true) {
// Acquire lock2 first
synchronized (lock2) {
// Acquire lock1 next
synchronized (lock1) {
System.out.println("Method 2");
}
}
}
}

public static void main(String[] args) {
final DeadLockDemo deadLockDemo = new DeadLockDemo();
Thread thread1 = new Thread() {
public void run() {
deadLockDemo.method1();
}
};

Thread thread2 = new Thread() {
public void run() {
deadLockDemo.method2();
}
};

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

How do we avoid this deadlock here? The typical answers like "synchronizing" the code doesn't solve the problem. Actually, deadlock happens because of improper synchronization. The answer is very simple though. Always acquire the locks in the same order. That is, acquire lock1 and then lock2 or lock2 and then lock1. Yes, it's as simple as that. You can try running the code and check it for yourself.

Till then, happy multi-threading!
Srikanth

Monday, August 27, 2007

Java :: FindBugs :: Dead Store

I ran FindBugs on one of our projects and I had a warning on some code similar to this, let's see how the code was written. This is just a sample code to show an example, don't expect any logic here :-)

// DeadStoreExample.java
import java.util.ArrayList;
import java.util.List;

public class DeadStoreExample {
public static void main(String[] args) {
List list = new ArrayList(); // Dead Store here.
list = getList();
System.out.println(list);
}

private static List getList() {
// Some intense operation and finally we return a java.util.List
return new ArrayList();
}
}

FindBugs reported me this problem: Dead store to list in DeadStoreExample.main(String[]). When I first saw it, I was like "What do you mean by Dead Store?" And when I looked into the code I saw a List object being created but not used. Instead, in the next line the reference variable is pointing to some other object in the heap. The object created on line number 6 is never used and hence it's a dead store.

So, what is a Dead Store? If we assign a value to a local variable, but the value is not read by any subsequent instruction, then it's called a Dead Store.

I love FindBugs, the thing that I like the most about FindBugs is that it tries to find all the lame bugs which many veteran programmers accidentally make. I always like to set my compiler warnings very high (even for my Javadoc comments). And now I have developed a habit of running FindBugs before I make a build or commit my code. It's one of those things like Unit Testing, you must try and get infected.

If a compiler or a tool can catch a bug, then I will always go for it. No one can write bug free code, at least I have not seen anyone till now. And I believe in automating anything that is possible so that we never have to do that manually again. That's why we have computers :-)

If you're not using FindBugs, I highly recommend that you to use it.

Monday, April 2, 2007

Java :: Constants Interface or Constants Class?

We all know about patterns and anti-patterns. One anti-pattern that has been hated by many people is the Constant Interface anti-pattern. Java doesn't support globals directly, but sometimes you will need to have a few things as global. Meaning, accessible to every class in your entire program.

In Java to get the platform independent new line character, we write the following code:

final String NEW_LINE = System.getProperty("line.separator");

But the new line character is something any class in our program may need and writing System.getProperty("line.separator") is not good for two reasons.
  1. We may misspell the key 'line.separator' in which case we'll get a 'null' back, and
  2. It's inefficient.
A better way is to get this new line character one time, store it in the memory and make it accessible to all the classes in our program. This kind of a situation led to the invention of the "Constant Interface" anti-pattern. People implemented this pattern like this:

public interface Constants {
String NEW_LINE = System.getProperty("line.separator");
}

And the client of this 'Constants' interface started implementing this interface for convenience reasons. This is a bad idea because let's say this 'Constants' interface has 100 constants and a client class implements this interface for convenience reasons, all the 100 constants from the interface end up being a part of the public API of the client class. This breaks inheritance and you can by now imagine how the Javadoc will look like for this client class.

OK, we may ask all of our clients of this 'Constants' interface that they must not implement this interface and they should only see it as a place where global constants are stored, but what's the guarantee that they will NOT implement this interface?

Thankfully we have a better way of doing this, see the following code:

public class Constants {
public static final String NEW_LINE = System.getProperty("line.separator");

private Constants() {
// Private constructor to enforce un-instantiability.
}
}

The above 'Constants' class has the following benefits over the 'Constants' interface:
  1. No client can instantiate, because the constructor is private
  2. No client can extend, again for the same reason, the constructor is private
Having a class for constants and making it's constructor private is a much better approach than using an interface.

Friday, March 30, 2007

Java :: Static Inner Classes

We all know that Java supports the creation of inner classes. Some people intentionally avoid creating inner classes for many good reasons. And also, one should avoid creating non-static inner classes without a very solid reason. Till now I have never created a non-static inner class except for the anonymous inner classes that I created for event-listeners in GUI programming.

But recently I started using static-inner classes for various purposes and it has tremendously improved my code's readability. Currently I'm using it for two purposes.
  1. Creating Private Utilities
  2. Creating Private Implementations
Creating Private Utilities

What do I mean by "Private Utilities"? We have classes like SwingUtilities, Math, etc. They all contain only "public static" methods and they enforce non instantiability by means of a private constructor. These are public utility classes, but not all the utility classes we create must be public. There are times you will need to have them private. For example, you want to implement your own FileFilter but you don't want to make it public or even package-private. And you also don't want to create that implementation as an anonymous inner class because you think it may clutter the code.

This is a perfect reason for creating a "private static" inner class.

Creating Private Implementations

Just open the source code of java.util.Hashtable and you will see 2 private static inner classes: EmptyEnumerator, and EmptyIterator. When we invoke Hashtable.keys() method, it first checks if the Hashtable has any elements in it. If the number of elements in the Hashtable is 0, it returns an instance of EmptyEnumeration which is a private implementation of java.util.Enumeration interface for empty Hashtable.

These are only a very few applications of static inner classes. I see them as a tool that can make my code more readable, elegant and efficient.

Tuesday, March 27, 2007

Java :: Exceptions :: Nested Exceptions

There is a nice little thing that got introduced in Java 1.4, it's nested exceptions.

Consider the following piece of code:

class LowLevelException extends Exception {
public LowLevelException(String message) {
super(message);
}
}

class HighLevelException extends Exception {
public HighLevelException(String message, Throwable cause) {
super(message, cause);
}
}

public class TryNestedExceptions {
public static void main(String[] args) {
try {
throw new LowLevelException("LowLevelException here.");
} catch(LowLevelException e) {
// While throwing a higher level exception, construct it with
// the LowLevelException as the cause.
try {
throw new HighLevelException("HighLevelException here.", e);
} catch (HighLevelException e1) {
e1.printStackTrace();
}
}
}
}

Let's see the stack trace of the above program:

HighLevelException: HighLevelException here.
at TryNestedExceptions.main(TryNestedExceptions.java:21)
Caused by: LowLevelException: LowLevelException here.
at TryNestedExceptions.main(TryNestedExceptions.java:16)

We also have stack trace of the LowLevelException in the "Caused by:" of HighLevelException's stack trace. This helps us to drill down to the root of the problem. I like the nested exception idea very much. We can nest as many exceptions as we want. For example, if the LowLevelException was caused due to some IOException then while throwing LowLevelException we can nest the IOException.