Today marks the official(ish) release of GlassFish v3. v3 is the product of years of hard work in what is, in some ways, a rewrite of v2. Built on top of OSGi, v3 offers a modularity and extensibility leap over v2. It’s also the first to fully support the JEE 6 specification. I’ve been a spring guy for a long time now but honestly (and employer imposed bias aside) JEE 6 makes a compelling case for skipping spring altogether. At least for my uses.
GlassFish v3 and JEE 6 offers a number of profiles so you can install as much or as little as you’d like. Using the web profile gives you everything you need to run many web apps. You can add additional features via the updatecenter as you need them often without needing to restart the server. If you’re a v2 user most of that should be very familiar to you already. Borrowing from Eduardo’s blog entry:
Key links available now:
• GlassFish v3 Main Product Page
• JavaEE 6 Hub
• JavaEE 6 Downloads (multiple bundles)
• Java EE 6 Feature Article (also see Overview White Paper).
You can read more here. You can also find all the GlassFish v3 related blogs on blogs.sun.com (at least those tagged as such) here. I’m really quite excited about this release but at the risk of sounding too press releasey about it all, I’ll leave the gushing to others. You can check it for yourself by downloading it.
Download it. Kick the tires. Take it for a spin. I think you’re going to like what you find. Especially if you haven’t given glassfish a look in some time. This is truly a different creature.
Technorati Tags: glassfish, glassfishv3, Java
Everyone hates the deprecation policies of the JDK team but it’s certainly an understandable policy. Millions and millions of lines of code exist out in the wild and there’s no telling what calamity would befall us if methods were actually removed the JRE libs. On the other hand, people still use those deprecated methods despite their failings and the presence of better options. I was reading Joseph Darcy’s blog entry on this policy and ran across an interesting comment.
The idea is pretty simple: make compiling fail against the deprecated methods without actually removing them from code. This preserves binary compatibility while preventing any new code from compiling against these methods. This would actually include new releases of applications written before the method was deprecated as these new versions would no longer compile while the previous releases would still run.
This seems to be the best of both worlds. Building on the idea from comment, I’d offer this enhancement: Introduce an @Obsolete annotation. This would supplant the @Deprecated annotation on these methods. Any usage of a method or class (or field?) with this annotation would return an error at compile time. Reflective access to these items would also be disallowed just to drive the point home. Of course, the annotations would need to include facilities to describe the alternatives to use for these old methods to provide the same functionality as the javadoc comment. Given this simple addition, I think we’d finally start to make some progress on modernizing our code.
Technorati Tags: development, Java
It’s friday night. Finally back at the hotel without a meeting or party or a session to go to. What else is there to do but port benchmarks of debatable value to my favorite new non-Java language: Fan. Earlier in the I was directed to this blog post detailing some performance problems with groovy. Yes, I know the blog is old. That’s not the point I want to make here. This week at Javaone, there was a presentation doing some more performance comparisons between languages on the JVM. This one caught my eye because it’s the first one I’ve seen in the wild that included Fan. So this got me thinking about year old post and the ray tracing exercise. How would fan hold up? I decided to find out. Because there’s no better way to spend a Friday night after long conference week, right?
The Fan code isn’t idiomatic (I’m not that bored tonight). It’s just a quick and dirty port from the Java source to Fan. For reference, I reran the Java version and then the Fan version. This test is running on OS X and Java 1.6u13. Without further hand waving, here’s the results:
time java -cp . ray 8 512
real 0m14.210s
user 0m12.443s
sys 0m1.313s
time fan tracer::RayTest 8 512
real 0m17.700s
user 0m15.832s
sys 0m0.672s |
As you can see, the performance is really quite good. I’ll probably play with the source over the next few days and see if I can’t improve it a bit. The fan code is pretty rough so there’s probably a fair bit to be done to speed that up a bit. I’ll attach the source so if anyone else is interested the source will be available. I have to say, though, that’s not too shabby at all.
Technorati Tags: fan, Java
I had intended to do some follow up numbers to my previous post but I got a bit sidetracked by work and the like. My simple tests all work with one String that’s created then thrown away. This test helped me resolve the question I had when I started down that road but stops short of a more general answer. Then I saw this pingback which led me here. There’s some nice analysis and insights to consider. So given the shortcomings of my little benchmark and the comments there, I wanted to expand my test a bit and see what things look like when the loop doesn’t throw away the data. The test is simple enough again:
import java.util.*;
import java.text.*;
public class ConcatenationTest {
private static long concat(int count) {
long start = System.currentTimeMillis();
for(int x = 0; x < count; x++) {
String s = "Loop " + x + " of " + count + " iterations.";
}
return System.currentTimeMillis() - start;
}
private static long append(int count) {
long start = System.currentTimeMillis();
for(int x = 0; x < count; x++) {
String s = new StringBuilder("Loop ")
.append(x)
.append(" of ")
.append(count)
.append("iterations.")
.toString();
}
return System.currentTimeMillis() - start;
}
private static long concatAcrossLoops(int count) {
long start = System.currentTimeMillis();
String s = "";
for(int x = 0; x < count; x++) {
s += "Loop " + x + " of " + count + " iterations.";
}
long time = System.currentTimeMillis() - start;
System.out.println("concatAcrossLoops time = " + time);
return time;
}
private static long appendAcrossLoops(int count) {
long start = System.currentTimeMillis();
StringBuilder s = new StringBuilder();
for(int x = 0; x < count; x++) {
s.append("\nLoop ")
.append(x)
.append(" of ")
.append(count)
.append("iterations.");
}
long time = System.currentTimeMillis() - start;
System.out.println("appendAcrossLoops time = " + time);
return time;
}
public static void main(String[] args) {
int count = 10000;
List concats = new ArrayList();
List appends = new ArrayList();
List concatsAcross = new ArrayList();
List appendsAcross = new ArrayList();
for(int x = 0; x < 10; x++) {
concats.add(concat(count));
appends.add(append(count));
concatsAcross.add(concatAcrossLoops(count));
appendsAcross.add(appendAcrossLoops(count));
}
String header = "concats appends concats across loops appends across loops";
String format = "%7d %9d %22d %22d\n";
System.out.println(header);
for(int x = 0; x < 10; x++) {
System.out.printf(format, concats.get(x), appends.get(x), concatsAcross.get(x), appendsAcross.get(x));
}
}
} |
And then the results:
| concats |
appends |
concats across loops |
appends across loops |
| 48 |
14 |
18990 |
1276 |
| 27 |
11 |
14581 |
1442 |
| 4 |
4 |
13206 |
1253 |
| 3 |
3 |
13478 |
1438 |
| 4 |
4 |
12651 |
1444 |
| 4 |
3 |
12485 |
1403 |
| 4 |
3 |
12608 |
1318 |
| 4 |
3 |
13152 |
1312 |
| 3 |
4 |
12535 |
1390 |
| 4 |
3 |
12444 |
1329 |
Notice after the first two loops the numbers for all runs drops. As the JIT compiler kicks in, we get some optimization but as you can see concatenation across loop iterations is incredibly much more expensive. In this case, StringBuilder is still the clear winner.
update
There was a typo in the original test. I was calling toString() in the appendsAcrossLoop test which was entirely unnecessary. (I forgot to remove that call when adapting from the earlier iteration.) The new results are below. I included them here rather than just replacing the table above as it shows just how expensive that toString() is.
| concats |
appends |
concats across loops |
appends across loops |
| 42 |
15 |
16562 |
4 |
| 5 |
8 |
12564 |
5 |
| 4 |
3 |
11601 |
2 |
| 4 |
2 |
11141 |
2 |
| 4 |
3 |
11025 |
3 |
| 3 |
3 |
11260 |
3 |
| 3 |
3 |
11062 |
3 |
| 3 |
3 |
11738 |
2 |
| 4 |
2 |
11078 |
2 |
| 4 |
2 |
11130 |
3 |
Technorati Tags: development, Java, justin lee
What’s the motivation for gcj these days? Originally, everyone wanted a GPLd JVM so gcj kinda made sense. At least in spirit. It’s never been a functional equivalent for an actual JVM, though. I’ve seen nothing but problems with it for years in IRC channels. It’s partial implementation of the spec has led to endless confusion for uncounted newbies coming to the java channel for help. It doesn’t help that the ideologues at Debian, et. al, continue to package gcj as if it were java. Well, we have a GPLd JVM now. Everything about it is open source (or just about done…).
GCJ, as I see it, serves no more useful purpose than allowing those in charge of it to hold on to some ideal (or maybe pride). I know this is inflammatory for a good number of people, but why persist? Is it the native compilation you like? The slow, misbegotten catastrophe that it is? It’s slower than running java bytecode and seems to eliminate several key features of Java (like dynamic classloading). Even before Sun GPLd their (our? I’m a Sun guy after all…) JVM, gcj adoption was miniscule at best. So, what’s the point? Can’t we move on from gcj? Or at a minimum, stop packaging it as the default JVM when it’s not actually a java implementation? That’d work for me. I’m just tired of seeing newbies getting tripped up by some distro’s ideological navel gazing.
Technorati Tags: gcj, Java, java 6, justin lee