Thursday, January 28, 2010

Find the version number of a .class file

If you see the error:
 java.lang.UnsupportedClassVersionError: Bad version number in .class file
it means that the Java ClassLoader cannot load a certain class because it has been compiled using a different version of the JDK. For example, you might see this error if your application has been compiled using Java 1.5, but an external library you are calling has been compiled using 1.6.

You can use the javap command to find out what the version number of a class file is:

sharfah@starship:~> javap -v MyApp | grep version
  minor version: 0
  major version: 50
50 refers to Java 1.6, while 49 refers to Java 1.5.

Tuesday, January 19, 2010

Difference between $*, $@, "$*" and "$@"

They are all related to "all the arguments to the shell", but behave differently. The following script demonstrates each one of $*, $@, "$@" and "$*" in turn by echoing out the arguments passed in:
#! /bin/bash

echo +--- Using "\$*"

cnt=1
for i in $*
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using \"\$*\"

cnt=1
for i in "$*"
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using "\$@"

cnt=1
for i in $@
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done

echo +--- Using \"\$@\"

cnt=1
for i in "$@"
do
  echo arg$cnt: $i
  cnt=$(($cnt+1))
done
Running the script, produces the following output:
sharfah@starship:~> echoArgs.sh  mars "kit kat" twix
+--- Using $*
arg1: mars
arg2: kit
arg3: kat
arg4: twix
+--- Using "$*"
arg1: mars kit kat twix
+--- Using $@
arg1: mars
arg2: kit
arg3: kat
arg4: twix
+--- Using "$@"
arg1: mars
arg2: kit kat
arg3: twix
When unquoted, $* and $@ do the same thing. They treat each "word" (sequence of non-whitespace characters) as a separate argument. This leads to the single argument "kit kat" being broken into two which may not be desired. When quoted, $* and $@ behave differently. "$*" treats the entire argument list as a single argument, but "$@" treats the arguments just as they were when passed in.

So, which should you use? In almost all cases you would use "$@" in order to preserve arguments with spaces (or quoted arguments) when being passed in on the command line or from one script to another. Never use the unquoted $* or $@ unless you are absolutely sure that you won't need to deal with arguments with spaces in them. If you need to combine all arguments into one, use "$*".

Monday, January 18, 2010

Java equals() Method

According to the Javadocs, the equals method must be:
  • reflexive: for any non-null reference value x, x.equals(x) should return true.
  • symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • return false for x.equals(null), for any non-null reference value x.
In other words, the following tests must pass:
@Test
public void testEquals() {

  // reflexive
  assertTrue(x.equals(x));

  // symmetric
  assertTrue(x.equals(y) == y.equals(x));

  // transitive
  if (x.equals(y) && y.equals(z)) {
    assertTrue(x.equals(z));
  }

  // consistent
  assertTrue(x.equals(y) == x.equals(y));

  // null check
  assertFalse(x.equals(null));
}
Implementing Equals(): Approach 1
The steps are:
  1. Check reference equality (good optimisation step)
  2. Check correct class type using instanceof
  3. Cast to correct type
  4. Compare objects
@Override
public boolean equals(Object obj) {

  // check reference equality
  if (this == obj) {
    return true;
  }

  // check correct arg type
  if (!(obj instanceof Rectangle)) {
    return false;
  }

  // cast the object to the correct type
  Rectangle other = (Rectangle) obj;

  // compare fields
  return other.getLength() == length &&
         other.getWidth()  == width;
}
But what happens if you extend this class by adding another field? For example, a Rectangle has a length and width. But what if we create a Cuboid that extends Rectangle with an additional depth attribute?

The problem occurs when you mix objects of Rectangle and Cuboid because Rectangle instanceof Cuboid returns false, whereas Cuboid instanceof Rectangle returns true. This breaks the symmetric rule because rectangle.equals(cuboid) is true, but cuboid.equals(rectangle) is false. In order to preserve symmetry, we can change our equals method as follows:

Implementing Equals(): Approach 2

  1. Check if null
  2. Check correct class type using getClass
  3. Cast to correct type
  4. Compare objects
@Override
public boolean equals(Object obj) {

  // check null
  if (obj == null) {
      return false;
  }

  //check correct type
  if(getClass() != obj.getClass()) {
      return false;
  }
  // cast the object to the correct type
  Rectangle other = (Rectangle) obj;

  // compare fields
  return other.getLength() == length &&
         other.getWidth()  == width;
}
The getClass method will always return false if the parameter is not the exact same type as the object class.

In most cases, you should use Approach 2 so that you obey the equals contract, unless you want to compare subclasses with their base types.

Friday, January 15, 2010

Interview Questions

Here are a few questions you may be asked if interviewing for a technology / developer role in an investment bank:

Java:

  • What is object orientation?
  • State three fundamental concepts in object-oriented programming (e.g encapsulation, abstraction, inheritance)?
  • What is the super class of all classes?
  • State three methods of the Object class.
  • What is the difference between checked and unchecked exceptions?
  • Name the subclasses of Throwable.
  • What is the Error class?
  • Why are hashcode() and equals() important?
  • What is hashcode() used for in a Hashmap?
  • Write an equals method for a Person class which contains a String attribute called name.
  • List XML parsers and how would you decide if you should use SAX or DOM?
  • Discuss testing with JUnit.
Oracle:
  • Given an Employee (name, dept_id) table and a Department (id, name) table, write a query to display which department each employee belongs to and another query to list all departments which have exactly 10 employees.
  • What steps would you take to identify why a query is slow and how would you optimise it?
  • What kinds of Hints are there?
  • What is the difference between a normal index and a clustered index?
Problem Solving:
  • You have 8 coins which look identical. However, one of them is heavier than the rest. You have a weighing scale. Find the heaviest coin using the scale the fewest times as possible.
    Answer: Weigh coins 1,2,3 vs 4,5,6. If they weigh the same, weigh 7 vs 8 to get the heaviest. If they are not the same, pick the heaviest batch (e.g. 1,2,3) and weigh 1 vs 2,3 and so on.
  • In the diagram below, you have two lists. Change the ordering of the elements in the first list, so that they appear in the same order as the second list. You have a container which can hold only one element to help you.
  • A          B
    B          C
    C   +--+   D
    D   |  |   E
    E   +--+   F
    F          G
    G          A
    
    Answer: Put A into the container. Shift all elements up by one. Move A into the vacant slot in the bottom of the list.
Risk and PnL:
  • What is Real PnL?
  • What is attribution i.e. what attributes make this PnL?
  • What is explained and unexplained pnl?
  • What is Delta Risk and why is it important?
  • What market data do you need to calculate Delta Risk and how is it calculated?
  • What is a yield curve?
  • What is a volatility surface?
  • Real PnL: Profit and Loss compared to yesterday REAL_P+L = PVToday - PVYest
  • Attribution: What made this PnL such as The Greeks: Delta PnL, Gamma PnL, Theta PnL, Vega PnL, New deals, Dropped deals, Amended deals, Cash flows
  • PnL Explained: The addition of all these attributions that explains the Real PnL.
  • PnL Unexplained: The difference between the Real PnL and the Explained PnL.
  • The target is to get Unexplained as close to 0 as possible.
Related Posts:

Thursday, January 14, 2010

Cobertura - Ignore Logger Calls

I recently caught the testing bug and try to make sure that all the code I write is well tested and has 100% coverage. I use Cobertura, which is an excellent tool for measuring how much of your code is covered by tests. The coverage report it produces shows you what percentage of packages, classes, methods, lines and conditionals are covered and it highlights, in red, the lines in your source code which are not covered. I can now sleep better at night, knowing that my code is fully covered!

In order to use Cobertura, you just need to add the plugin to your project's POM file. When I first ran Cobertura, I found that it highlighted my logger.debug lines of code, so I had to tell it to ignore all logger calls, as follows:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <formats>
            <format>html</format>
        </formats>
        <instrumentation>
            <ignores>
                <ignore>org.apache.log4j.*</ignore>
            </ignores>
        </instrumentation>
    </configuration>
    <executions>
        <execution>
            <phase>deploy</phase>
            <goals>
                <goal>cobertura</goal>
            </goals>
        </execution>
    </executions>
</plugin>
You can run it using mvn cobertura:cobertura and then look at the report in target/site/cobertura/index.html.

Cobertura will also highlight some code which is impossible to test. For example, if a class has a private constructor (because it has static methods), then it will highlight the private constructor, even though you can't test it (unless you use reflection and change the constructor's accessibility, but that is going a bit too far!).

Tuesday, January 12, 2010

Identify which process is using a port

Linux:
Use the lsof command and grep for the port number you are interested in:
sharfah@starship:~>  lsof -Pan -i tcp -i udp | grep :8343
java    27725 sharfah    6u  IPv6 20486040       TCP *:8343 (LISTEN)
Solaris:
If you have lsof installed on Solaris, then you can use the Linux method above. If you don't have or cannot install lsof, then use the pre-installed pfiles in a loop, as shown below:
sharfah@starship:~>  ps -ef | grep myuser | awk '{print $2}' | while read pid
>do
>echo $pid
>pfiles $pid| grep 12197
>done
19424
16132
16040
29373
15946
25178
 121: S_IFREG mode:0640 dev:289,6 ino:259883 uid:50006 gid:106 size:109318
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
        peername: AF_INET 10.232.160.164  port: 12197
15985
16052
18758

Monday, January 11, 2010

Find Blocking Processes Using sp_who [Sybase]

If a user has executed an insert/update on a table, but not committed the transaction, other users will find that their queries on the same table hang. This is because the table has been locked and the first user's process is blocking everyone else's.

The following scenario illustrates this. User Bob updates a table but does not commit it. User Alice then tries to query the table, but here command hangs:

bob$ isql -S myServer -D myDatabase -U myUser -P myPass
1> begin transaction
2> update MY_TABLE set COL='C' where COL='A'
3> go
(1 row affected)

alice$ isql -S myServer -D myDatabase -U myUser -P myPass
1> select * from MY_TABLE where COL = 'A'
2> go -- Hangs
In this example, Alice's query to the table hangs because Bob has not committed his transaction. You can use the sp_who command in order to see which commands are blocked and who they are being blocked by.
alice$ isql -S myServer -D myDatabase -U myUser -P myPass
1> sp_who
2> go
fid spid status     loginame  origname  hostname                  blk_spid
        dbname      tempdbname cmd               block_xloid
--- ---- ---------- --------- --------- ------------------------- --------
         ----------- ---------- ----------------- -----------
  0   51 recv sleep myUser myUser MACHINE21302                     0
        myDatabase  tempdb     AWAITING COMMAND            0
  0  343 lock sleep myUser myUser MACHINE21501                    51
        myDatabase  tempdb     SELECT                      0
The output shows that spid 343 from MACHINE21501 is being blocked by spid 51 from MACHINE21302. You can use the command sp_lock 51 in order to find more information about the locking process.

You can either kill the blocking process (if you have DBA rights) using kill 51 or use the psloggedon utility to find out which user is logged onto MACHINE21302, so that you can tell them to commit their open transaction.

Find out who is logged on to a computer

Download PsTools from here which contains a suite of useful utilities. One of them is called psloggedon which allows you to see who is logged onto a specific computer.
C:\program files\PsTools>psloggedon.exe \\computername

loggedon v1.33 - See who's logged on
Copyright ® 2000-2006 Mark Russinovich
Sysinternals - www.sysinternals.com

Users logged on locally:
     Error: could not retrieve logon time
NT AUTHORITY\LOCAL SERVICE
     Error: could not retrieve logon time
NT AUTHORITY\NETWORK SERVICE
     Error: could not retrieve logon time
domain\xpid
     Error: could not retrieve logon time
NT AUTHORITY\SYSTEM

Users logged on via resource shares:
     11/01/2010 13:36:31    domain\myxpid

Friday, January 01, 2010

fahd.blog in 2009

Happy 2010!
I'd like to wish everyone a great start to an even greater new year!

During 2009, I posted 38 new entries on fahd.blog. I am also thrilled that I have more readers from all over the world too! Thanks for reading!

Top 5 posts of 2009:

I'm going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)