Hi,
I survey the issue Harmony-4942, found the Harmony's behavior of finding
"jndi.properties" file is not the same as ri's:
Harmony re-search the whole CLASSPATH every construction time, while ri
just search once when using a classloader to
find the file at first time. The following code prove it:
=============begin=============
URL url = new File("test1").toURL();
URLClassLoader cltest1 = new URLClassLoader(new URL[] { url },
Thread.currentThread().getContextClassLoader());
Thread test1 = new Thread(new Runnable() {
public void run() {
try {
System.out.println("test1 classloader"
+ Thread.currentThread()
.getContextClassLoader());
FileOutputStream fos = new FileOutputStream(
"test1/jndi.properties");
PrintStream ps = new PrintStream(fos);
ps
.println("java.naming.factory.initial=regis.jndi.MyDefaultInitialContextFactory");
ps.println("java.naming.provider.url=http://test1");
ps.close();
InitialContext context = new InitialContext();
System.out.println("test1.context= " + context);
System.out.println("test1.context.env="
+ context.getEnvironment());
File file = new File("test1/jndi.properties");
file.delete();
// create new properties file with different values
fos = new FileOutputStream(
"test1/jndi.properties");
ps = new PrintStream(fos);
ps
.println("java.naming.factory.initial=regis.jndi.MyDefaultInitialContextFactory");
ps.println("java.naming.provider.url=http://test1.new");
ps.close();
context = new InitialContext();
System.out.println("test1.new.context=" + context);
System.out.println("test1.new.context.env="
+ context.getEnvironment());
} catch (Exception e) {
e.printStackTrace();
}
}
});
// use different classloader
test1.setContextClassLoader(cltest1);
test1.start();
url = new File("test2").toURL();
URLClassLoader clSrc = new URLClassLoader(new URL[] { url
}, Thread
.currentThread().getContextClassLoader());
Thread test2 = new Thread(new Runnable() {
public void run() {
try {
System.out.println("test2 classloader"
+ Thread.currentThread()
.getContextClassLoader());
FileOutputStream fos = new FileOutputStream(
"test2/jndi.properties");
PrintStream ps = new PrintStream(fos);
ps
.println("java.naming.factory.initial=regis.jndi.MyDefaultInitialContextFactory");
ps.println("java.naming.provider.url=http://test2");
ps.close();
InitialContext context = new InitialContext();
System.out.println("test2.context= " + context);
System.out.println("test2.context.env="
+ context.getEnvironment());
} catch (Exception e) {
e.printStackTrace();
}
}
});
// use different classloader
test2.setContextClassLoader(clSrc);
test2.start();
===================end=================
(I slightly modify MyDefaultInitialContextFactory, add environment
values to MyInitialContext after initial)
the output is below, using jre1.6.0:
============start output===============
test1 [EMAIL PROTECTED]
test1.context= [EMAIL PROTECTED]
test1.context.env={java.naming.factory.initial=regis.jndi.MyDefaultInitialContextFactory,
java.naming.provider.url=http://test1}
[EMAIL PROTECTED]
test1.new.context.env={java.naming.factory.initial=regis.jndi.MyDefaultInitialContextFactory,
java.naming.provider.url=http://test1}
test2 [EMAIL PROTECTED]
test2.context= [EMAIL PROTECTED]
test2.context.env={java.naming.factory.initial=regis.jndi.MyDefaultInitialContextFactory,
java.naming.provider.url=http://test2}
=============end output=================
So under same classloader, ri just search property file once.
In harmony we can use a map to hold property values for each classloader
to avoid search at every construction time.
But i found Harmony is still slower than ri at first time to constuct
InitialContext object, the most time is consumed at
org.apache.harmony.jndi.internal.EnvironmentReader line 233:
p.load(is);
Then i write some sample code to test performance of Properties.load():
Properties pro = new Properties();
URL url = new
URL("jar:file:/home/bahamut/harmony/trunk/deploy/jdk/jre/lib/boot/jndi.jar!/jndi.properties");
InputStream in = url.openStream();
long start = System.currentTimeMillis();
pro.load(in);
long end = System.currentTimeMillis();
System.out.println("time: " + (end - start));
in.close();
pro = new Properties();
url = new
URL("jar:file:/home/bahamut/harmony/trunk/deploy/jdk/jre/lib/boot/jndi.jar!/jndi.properties");
in = url.openStream();
start = System.currentTimeMillis();
pro.load(in);
end = System.currentTimeMillis();
System.out.println("time: " + (end - start));
in.close();
output of ri:
time: 1
time: 0
output of harmony:
time: 231
time: 1
Harmony is slower than ri *two hundred* times!!
in above test, property file is in jndi.jar about 230k, if not in jar
file, the time of harmony and ri are very close,
so i think there must be some problems of archive module. Is it because
of we using different algorithm with ri,
or our implementation has bugs?
Best Regards,
Regis.