The Mysterious Case of the Missing BigDecimal Constructor

My current project has recently been experiencing runtime exceptions of the form:

NoSuchMethodError: java.math.BigDecimal.<init>(I)V

These exceptions only showed up when we started creating a codebase that mixes code written for Java 1.4 and code written for Java 1.5 (we wanted our design to use generics and annotations).

Looking at the stack trace it was clear that the source of the runtime exception was construction of a BigDecimal using an int argument, for example, new BigDecimal(5). Looking over the Java API reveals that in Java 1.5 BigDecimal has a constructor that takes a double or an int argument while in Java 1.4 BigDecimal has no constructor that takes an int argument.

Working through all the permutations with a colleague we were able to create the runtime exception when we built our code using a Java 1.5 build path, compiling for Java 1.4, and running the code on a Java 1.4 JVM. It turned out that the key mistake was to use the Java 1.5 build path. This only happened on certain misconfigured developer machines. Once we reconfigured the developer machines the runtime exception was gone.

Still, I was curious and I wanted to really understand the runtime exception. I installed the Bytecode Outline plugin for Eclipse so that I could see the bytecodes generated for new BigDecimal(5). You could also use the javap command line tool. Below are the interesting fragments of bytecode.

Build Path: 1.4.2

NEW java/math/BigDecimal
DUP
LDC 5.0
INVOKESPECIAL java/math/BigDecimal.<init>(D)V

Build Path: 1.5.0

NEW java/math/BigDecimal
DUP
ICONST_5
INVOKESPECIAL java/math/BigDecimal.<init>(I)V

Now it is easy to see what is going on. When the build path is for Java 1.4 the compiler converts the int literal 5 to a double. When the build path is for Java 1.5 the compiler generates a call to a constructor that takes an int argument—a method that does not exist in the 1.4 runtime libraries.

Case closed.

If you want to know the meaning of operands such as DUP and LDC, you can read Chapter 6 of The Java Virtual Machine Specification.

2 Comments

AnonymousFebruary 13th, 2009 at 7:27 am

We were stumped by this idiosyncrasy.
Awesome analysis!!

Thank you.

TotoMarch 24th, 2009 at 9:16 am

I have exactly this problem when using the constructor BigDecimal big = new BigDecimal(0) and so resolved by BigDecimal big = new BigDecimal(“0”) or another solution is to cast the value
BigDecimal big = new BigDecimal((double)0)

Leave a comment

Your comment