Tuesday, August 16, 2005
If you can't join them
"If you can't join them, beat them." - They didn't want me to join them. Granted. I'll now beat them whenever we face-off. That's a promise. I'll make them regret this. Promises to be fun.
Tuesday, August 09, 2005
Thursday, July 21, 2005
Good Quote
Found this excellent quote on the google home page:
"Getting ahead in a difficult profession requires avid faith in yourself. That is why some people with mediocre talent, but with great inner drive, go much further than people with vastly superior talent."
- Sophia Loren
"Getting ahead in a difficult profession requires avid faith in yourself. That is why some people with mediocre talent, but with great inner drive, go much further than people with vastly superior talent."
- Sophia Loren
Friday, July 15, 2005
Application Versioning
Tom ball explains how class loading can be used to achieve simple application versioning -
Versioning, which I'm defining for this entry as how a Java application manages its external library dependencies, has been a tough issue ever since Java first released. Back when Java was born, the vision was that each machine would have a single Java runtime and standard libraries which would always be fully backwards-compatible. The reality has been that for most apps, the only reasonable alternative to testing a full matrix of released JREs and libraries is to instead package everything the app needs, install the whole hairball on each customer's system and use a custom classpath to access it. The problem with a custom classpath is that it is easy for your customers to break in subtle (and not so subtle) ways, which makes them cranky and can drive your tech support engineers crazy. Some work has been done in the JDK via its Package Versioning Specification and API, but there are still times when your app really needs to keep specific libraries under tight control.
NetBeans has this problem with its
Now, we need to interact with classes loaded by this classloader. What works best for us is to define a simple interface which the versioned classes and their client code shares, and a factory class that uses reflection to load the class which implements that interface (in 1.0, you needed a default constructor and used Class.newInstance()). Here's a simplified example (from the same Factory class):
There is one thing to watch for (there always is), however: sometimes you can find yourself pondering the impossible, like I did yesterday:

What caught me off-guard is that the debugger shows the type of "ex" is EmptyScriptException, but if it were that type then it should have been caught by previous catch block. Worse, a "(ex instanceof EmptyScriptException)" watchpoint returns "false", when it "obviously" should be true. The issue is that a class isn't just defined by its bytecode (the classfile's contents), but by the combination of bytecode and classloader. Here, there were two copies of EmptyScriptException loaded: once by Jackpot's private classloader, and once by the NetBeans one. Instances of one class copy will fail instanceof and catch tests with the other. I frequently forget this subtlety until reminded by a few head bangs against my monitor. The fix is to add the class to your list of classes which your classloader ignores and therefore shares with its parent classloader.
Over time, I have learned the value of this behavior (the classes not mixing, not the head banging). Since I'm pretty lazy, the extra work required to share classes between classloaders means that my designs do as little class sharing as possible. It is easier to maintain a really strict isolation with only a few, simple interfaces, than it is to maintain a big list of shared classes and deal with the headaches of managing their dependencies. A nice bonus is that this sort of isolation lends itself to distributed and parallel designs, where the more lightly coupled remote objects are to each other, the better they work together. Besides, it's hard to convince your manager you need the latest fire-breathing multi-processor workstation if your design is hopelessly interlocked.
This blog entry is way too long. I hope however that it dispells the idea that writing a classloader is rocket-science or limited to a few obscure uses. Managing application versioning is a problem many application teams face, and some judicious classloading can make it much easier.
Versioning, which I'm defining for this entry as how a Java application manages its external library dependencies, has been a tough issue ever since Java first released. Back when Java was born, the vision was that each machine would have a single Java runtime and standard libraries which would always be fully backwards-compatible. The reality has been that for most apps, the only reasonable alternative to testing a full matrix of released JREs and libraries is to instead package everything the app needs, install the whole hairball on each customer's system and use a custom classpath to access it. The problem with a custom classpath is that it is easy for your customers to break in subtle (and not so subtle) ways, which makes them cranky and can drive your tech support engineers crazy. Some work has been done in the JDK via its Package Versioning Specification and API, but there are still times when your app really needs to keep specific libraries under tight control.
NetBeans has this problem with its
javac bridge, which allows its editor and refactoring modules access to javac's error checking and parsing support. The problem is that javac doesn't have a public API, so while a tool can leverage a specific version of javac, it cannot rely on whatever is on the customer's machine since its internal API may be radically different. We have a recent version of javac that works with our bridge, but just adding it to the NetBeans classpath won't work for two reasons:- NetBeans supports many different JDKs, each of which have their own version of javac; and
- The Mac OS X includes the javac classes in its bootclasspath (and supportable products shouldn't whack the bootclasspath if possible).
private static class GJASTClassLoader extends URLClassLoader {
private final PermissionCollection permissions = new Permissions();
public GJASTClassLoader(URL gjastJar) {
super(new URL[] {gjastJar}, Factory.class.getClassLoader());
permissions.add(new AllPermission());
}
protected Class loadClass(String n, boolean r) throws ClassNotFoundException {
if (n.startsWith("com.sun.tools.javac") || n.startsWith("org.netbeans.lib.gjast")) {
// Do not proxy to parent!
Class c = findLoadedClass(n);
if (c != null) return c;
c = findClass(n);
if (r) resolveClass(c);
return c;
} else {
return super.loadClass(n, r);
}
}
protected PermissionCollection getPermissions(CodeSource codesource) {
return permissions;
}
}
As you can see, we rely on URLClassLoader to do all the heavy lifting. Our version isolation support is in loadClass(), where a test is made of the requested class name to see if it is in one of the packages to be isolated (here, we test whether the class is a javac or bridge class). If it is an isolated class, URLClassLoader.findLoadedClass() and findClass() look it up in the jar file we supplied in the constructor; otherwise we let URLClassLoader.loadClass() delegate to the parent classloader.Now, we need to interact with classes loaded by this classloader. What works best for us is to define a simple interface which the versioned classes and their client code shares, and a factory class that uses reflection to load the class which implements that interface (in 1.0, you needed a default constructor and used Class.newInstance()). Here's a simplified example (from the same Factory class):
public interface ErrorChecker {
int parse() throws CompilerException;
}
public final class Factory {
private static Factory instance = null;
private static Constructor newErrorChecker;
public static synchronized Factory getDefault() {
if (instance == null) {
instance = new Factory();
Class[] newCheckerTypes = new Class[] {
ECRequestDesc.class
};
File gjastJar = InstalledFileLocator.getDefault().locate("modules/ext/gjast.jar", "org.netbeans.modules.javacore", false);
try {
ClassLoader loader = new GJASTClassLoader(gjastJar.toURI().toURL());
Class c = Class.forName("org.netbeans.lib.gjast.ASErrorChecker", true, loader);
newErrorChecker = c.getConstructor(newCheckerTypes);
} catch (Exception e) {
}
}
return instance;
}
public ErrorChecker getErrorChecker(ECRequestDesc desc) {
try {
return (ErrorChecker) newErrorChecker.newInstance(new Object[] { desc });
} catch (Exception e) {
Throwable t = e.getCause();
throw new RuntimeException("Cannot create errorChecker: " +
t != null ? t : e);
}
}
}
In the above, we fetch the ASTErrorChecker constructor via reflection, then use it whenever the client requests a new ErrorChecker implementation. Because the interface doesn't directly or indirectly reference any class types in our private javac copy (CompilerException is also shared), objects created using its classes can interact with the client without conflict.There is one thing to watch for (there always is), however: sometimes you can find yourself pondering the impossible, like I did yesterday:
What caught me off-guard is that the debugger shows the type of "ex" is EmptyScriptException, but if it were that type then it should have been caught by previous catch block. Worse, a "(ex instanceof EmptyScriptException)" watchpoint returns "false", when it "obviously" should be true. The issue is that a class isn't just defined by its bytecode (the classfile's contents), but by the combination of bytecode and classloader. Here, there were two copies of EmptyScriptException loaded: once by Jackpot's private classloader, and once by the NetBeans one. Instances of one class copy will fail instanceof and catch tests with the other. I frequently forget this subtlety until reminded by a few head bangs against my monitor. The fix is to add the class to your list of classes which your classloader ignores and therefore shares with its parent classloader.
Over time, I have learned the value of this behavior (the classes not mixing, not the head banging). Since I'm pretty lazy, the extra work required to share classes between classloaders means that my designs do as little class sharing as possible. It is easier to maintain a really strict isolation with only a few, simple interfaces, than it is to maintain a big list of shared classes and deal with the headaches of managing their dependencies. A nice bonus is that this sort of isolation lends itself to distributed and parallel designs, where the more lightly coupled remote objects are to each other, the better they work together. Besides, it's hard to convince your manager you need the latest fire-breathing multi-processor workstation if your design is hopelessly interlocked.
This blog entry is way too long. I hope however that it dispells the idea that writing a classloader is rocket-science or limited to a few obscure uses. Managing application versioning is a problem many application teams face, and some judicious classloading can make it much easier.
Remember, no rocket science, this. :-)
Tuesday, July 12, 2005
Eclipse craves for matisse
Eclipse users are desperate for an answer to netBeans' "Matisse" gui builder. But there's no solace and no respite in sight.
I want to hear the eclipse zealots respond to this one.
Here's the bug report that begs for it. (Sadistic pleasure, this.)
The old order changeth. :-)
I want to hear the eclipse zealots respond to this one.
Here's the bug report that begs for it. (Sadistic pleasure, this.)
The old order changeth. :-)
Friday, July 08, 2005
Thursday, July 07, 2005
Tuesday, June 28, 2005
Sun's truce with IBM (for now)
InfoWorld reports -
In detailing IBM’s renewal of its Java agreement, Schwartz acknowledged that there has been “a little bit of a chill” in the relationship between the two vendors. But IBM and Sun announced an 11-year extension to their Java technology agreement. IBM will continue to license Java technologies from Sun including the Enterprise, Standard and Micro editions of Java as well as Java Card technologies. IBM also will continue participating in the Java Community Process.
In addition, IBM will port its DB2, Tivoli and WebSphere middleware to Sun’s Solaris 10 OS. The agreement, said Robert LeBlanc, general manager of the WebSphere product line at IBM, shows that IBM and Sun are in Java for the long haul.
Peace - and prosperity - for the community
In detailing IBM’s renewal of its Java agreement, Schwartz acknowledged that there has been “a little bit of a chill” in the relationship between the two vendors. But IBM and Sun announced an 11-year extension to their Java technology agreement. IBM will continue to license Java technologies from Sun including the Enterprise, Standard and Micro editions of Java as well as Java Card technologies. IBM also will continue participating in the Java Community Process.
In addition, IBM will port its DB2, Tivoli and WebSphere middleware to Sun’s Solaris 10 OS. The agreement, said Robert LeBlanc, general manager of the WebSphere product line at IBM, shows that IBM and Sun are in Java for the long haul.
Peace - and prosperity - for the community
Friday, June 24, 2005
Eclipse's "external" contributors
A good flame war on IBM's hypocritical claims of "the huge number of external contributors in Eclipse"
Friday, June 10, 2005
netBeans Abbreviations
You can add your own abbreviations (i.e editor shortcuts) to NB by creating/modifying the abbreviations.xml under [user-home-netbeans-dir]\4.1\config\Editors\text\x-java\.
Roman Strobl explains.
Roman Strobl explains.
Thursday, June 09, 2005
NetBeans overtakes Eclipse
NetBeans has surpassed Eclipse on the Daily Traffic Rank Trend on June 7th.
Here's the evidence.
Here's the evidence.
Contributing to the J2EE SDK (RI)
If the title interests you, this is where you should be headed - https://glassfish.dev.java.net
Wednesday, June 08, 2005
Tree felling around Sankey
I was alarmed to see trees lining the walking-track around Sankey Tank being felled this morning. But, on enquiring at the Deccan Herald office, I found out that they're following a carefully laid-out development plan for the peripheral areas of the lake. A committee is supposedly in place to carry out the planning & implementation of this. The reporter was kind enough to provide details about this. He even said that 2 new trees will be grown in place of every OLD tree chopped there. But, when I asked him if such "committees" were not acting as per their own whims & fancies, he just said, "We're hopeful that that's not the case & that all this is not an eyewash.We're keeping an eye on developments".
In retrospect, the press is probably the last powerful institution that's capable of protecting Bangalore's ecological balance. (Sigh)
In retrospect, the press is probably the last powerful institution that's capable of protecting Bangalore's ecological balance. (Sigh)
Tuesday, June 07, 2005
A Mac laptop running on Niagara?
Read this blog on ZDNet that goes like-
"So what can Apple do? What they should have done two years ago: hop into bed with Sun. Despite its current misadventure with Linux, Sun isn’t in the generic desktop computer business. The Java desktop is cool, but it’s a solution driven by necessity, not excellence. In comparison, putting MacOS X on the Sun Ray desktop would be an insanely great solution for Sun while having Sun’s sales people push SPARC based Macs onto corporate desktops would greatly strengthen Apple.
Most importantly, SPARC is an open specification with a number of fully qualified fabs. In the long term Apple wouldn’t be trapped again and in the short term the extra volume would improve prospects for both companies. Strategically, it just doesn’t get any better than that.
Niagara rocks. You want low power use for a laptop? How about an eight way 1.4Ghz SMP core with TCP/IP and cryptography done in hardware - at 65 watts flat out. There are some serious software issues, but get past them and you’ve got eight to ten Xeons in the box - at 65 watts.
Sun’s president, Jonathan Schwartz, put a nice invitation for you in his blog last Sunday. Maybe you should think about it..."
Sun folks(you need to pursue this...) & Apple folks, ARE YOU LISTENING??? Isn't this worth a try?
"So what can Apple do? What they should have done two years ago: hop into bed with Sun. Despite its current misadventure with Linux, Sun isn’t in the generic desktop computer business. The Java desktop is cool, but it’s a solution driven by necessity, not excellence. In comparison, putting MacOS X on the Sun Ray desktop would be an insanely great solution for Sun while having Sun’s sales people push SPARC based Macs onto corporate desktops would greatly strengthen Apple.
Most importantly, SPARC is an open specification with a number of fully qualified fabs. In the long term Apple wouldn’t be trapped again and in the short term the extra volume would improve prospects for both companies. Strategically, it just doesn’t get any better than that.
Niagara rocks. You want low power use for a laptop? How about an eight way 1.4Ghz SMP core with TCP/IP and cryptography done in hardware - at 65 watts flat out. There are some serious software issues, but get past them and you’ve got eight to ten Xeons in the box - at 65 watts.
Sun’s president, Jonathan Schwartz, put a nice invitation for you in his blog last Sunday. Maybe you should think about it..."
Sun folks(you need to pursue this...) & Apple folks, ARE YOU LISTENING??? Isn't this worth a try?
Monday, June 06, 2005
Sun:leading everywhere
Some really heartening developments :
1)The E20K kicks IBM's 32 way power 5 based server and one from HP that has a similar (but in the end - inferior) configuration.
2)The new netBeans gui builder simply rocks!!!
3) netBeans draws level with eclipse
4)Sun acquires storagetek to add to the procom IP acquisition and tarantella(on the secure,remote desktop front).
Hopefully, all these will see sun hitting back hard at its competitors in the quarters to come.
1)The E20K kicks IBM's 32 way power 5 based server and one from HP that has a similar (but in the end - inferior) configuration.
2)The new netBeans gui builder simply rocks!!!
3) netBeans draws level with eclipse
4)Sun acquires storagetek to add to the procom IP acquisition and tarantella(on the secure,remote desktop front).
Hopefully, all these will see sun hitting back hard at its competitors in the quarters to come.
Tuesday, May 31, 2005
Why clone is slower than newInstance
Ken Russell from the Java HotSpot VM Group, Sun Microsystems writes in java.net forums:
"Actually in the HotSpot JVM Object.clone() is not currently heavily optimized, while new instance is. You can feel free to file an RFE about this in the bug database. You can work around this problem by overriding clone() and manually allocate the new instance and assign the data into it. In fact, I think this is already probably necessary once your data structures get more complicated, which is why slow performance of Object.clone() hasn't shown up on our performance radar.
P.S. Here's a revised version of your test case which gets rid of startup transients:"
public class Main {
private boolean flag = true;
private String string = "Hello";
private int i = 0;
static class Child extends Main implements Cloneable {
private boolean flag2 = false;
private String string2 = "World";
private int i2 = -1;
}
private static int count = 1000000;
public static void testClone() throws CloneNotSupportedException {
Child child = new Child();
int res = 0;
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Child child2 = (Child) child.clone();
res += child2.i2;
}
long stopTime = System.currentTimeMillis();
System.out.println("" + count + " clones took " +
(stopTime - startTime) + " ms (dummy result = " + res + ")");
}
public static void testNewInstance() {
int res = 0;
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Child child = new Child();
res += child.i2;
}
long stopTime = System.currentTimeMillis();
System.out.println("" + count + " new operations took " +
(stopTime - startTime) + " ms (dummy result = " + res + ")");
}
public static void main(String[] args) throws CloneNotSupportedException {
testClone();
testClone();
testClone();
testNewInstance();
testNewInstance();
testNewInstance();
}
}
"Actually in the HotSpot JVM Object.clone() is not currently heavily optimized, while new instance is. You can feel free to file an RFE about this in the bug database. You can work around this problem by overriding clone() and manually allocate the new instance and assign the data into it. In fact, I think this is already probably necessary once your data structures get more complicated, which is why slow performance of Object.clone() hasn't shown up on our performance radar.
P.S. Here's a revised version of your test case which gets rid of startup transients:"
public class Main {
private boolean flag = true;
private String string = "Hello";
private int i = 0;
static class Child extends Main implements Cloneable {
private boolean flag2 = false;
private String string2 = "World";
private int i2 = -1;
}
private static int count = 1000000;
public static void testClone() throws CloneNotSupportedException {
Child child = new Child();
int res = 0;
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Child child2 = (Child) child.clone();
res += child2.i2;
}
long stopTime = System.currentTimeMillis();
System.out.println("" + count + " clones took " +
(stopTime - startTime) + " ms (dummy result = " + res + ")");
}
public static void testNewInstance() {
int res = 0;
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
Child child = new Child();
res += child.i2;
}
long stopTime = System.currentTimeMillis();
System.out.println("" + count + " new operations took " +
(stopTime - startTime) + " ms (dummy result = " + res + ")");
}
public static void main(String[] args) throws CloneNotSupportedException {
testClone();
testClone();
testClone();
testNewInstance();
testNewInstance();
testNewInstance();
}
}
Friday, May 27, 2005
Slashdot: In 72 Hours, Your Ban Will Be Lifted
Has this happened to you?
"Your Headline Reader Has Been Banned".Your RSS reader is abusing the Slashdot server. You are requesting pages more often than our terms of service allow. "Do Not Bother Contacting Us For 72 Hours".Very funny.
The faq page says this
"Your Headline Reader Has Been Banned".Your RSS reader is abusing the Slashdot server. You are requesting pages more often than our terms of service allow. "Do Not Bother Contacting Us For 72 Hours".Very funny.
The faq page says this
Subscribe to:
Posts (Atom)