A couple of things.
One is you need to "warm up" Java before measuring performance. This is because java will dynamically recompile and optimize code that is used heavily. So you should run a number of iterations before you start measuring.
Secondly your number of iterations is too small, at least one my i7 machine. Initially I reverse the order of the tests and the naive implementation came out on top, but after addressing those two issues it is a lot clearer:
Code:
Math.pow: 1795066524
naive pow: 122303010
optimized pow: 57139739
Math.pow loses, but that is obvious when you are only handling positive integer powers.
Would be good to have some specific tests around exp == 2 is, as it is generally the most common case. I expect the result is the same. Also need some unit tests showing the results are the correct, specifically around the edge scenarios like exp == 0, -1, 1, 2, and base == -1, 0, 1, 2 (for some of those cases you might need to hand over to Math.pow).
Ideally we would then add it to TeraMath as pow(float, int) and pow(double, int), and sit it along side a pow(float, double) and pow(double, double) that map to Math.pow().
Style-wise I would have some complaints, but I assume you're just prototyping. I would point out that there is no need to have D at the end of doubles though. If you want to be clear, include a .0 at the end, but otherwise all floating point numbers in Java are doubles unless a trailing f is included. Checkstyle complains about modifying function parameters, but we probably can turn that off for TeraMath.