Hi folks,

I noticed that RI behaves differently from spec when loading charset
provider. As spec says: "Charset providers are looked up via the current
thread's context class loader. " However, RI seems not using thread's
context class loader. Following test shows the case:

public class CharsetTest extends TestCase {
   public void test_providerCharset() throws Exception {
      Thread.currentThread().setContextClassLoader(new MyClassLoader());
      assertFalse(Charset.isSupported("abcdefg"));
   }
}

class MyClassLoader extends ClassLoader {
   protected Class findClass(String arg0) throws ClassNotFoundException {
       return null;
   }

   protected Enumeration findResources(String arg0) throws IOException {
       return null;
   }

   protected synchronized Class loadClass(String arg0, boolean arg1) throws
ClassNotFoundException {
       return null;
   }

   public Class loadClass(String arg0) throws ClassNotFoundException {
       return null;
   }

}
Additionally, place charset provider file named "
java.nio.charset.spi.CharsetProvider" under META-INF/services folder in your
classpath, and mock a simple CharsetProvider in your project, Like:
public class MyCharsetProvider extends CharsetProvider {
   public Iterator<Charset> charsets() {

       return null;
   }
   public Charset charsetForName(String arg0) {
       return null;
   }
}

The test passes against RI, which means RI doesn't use MyClassLoader to load
charset classes at all, since "loadClass" methods of MyClassLoader have been
overriden and always return null.

The test fails against Harmony, with following exception:

java.lang.Error: com.andrew.MyCharsetProvider
at java.nio.charset.Charset.searchConfiguredCharsets(Charset.java:404)
at java.nio.charset.Charset.forNameInternal(Charset.java:464)
at java.nio.charset.Charset.isSupported(Charset.java:532)
at com.andrew.CharsetTest.test_providerCharset(CharsetTest.java:26)
at java.lang.reflect.AccessibleObject.invokeV(AccessibleObject.java:205)
at java.lang.reflect.Method.invoke(Method.java:255)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(
RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(
RemoteTestRunner.java:196)
Caused by: java.lang.ClassNotFoundException: com.andrew.MyCharsetProvider
at java.lang.Class.forName(Class.java:157)
at java.nio.charset.Charset.searchConfiguredCharsets(Charset.java:398)
... 16 more

Currently, Harmony uses thread's context class loader, which conforms to
spec.

Shall we follow RI or spec? I'd like to suggest follow RI for this specific
case, because:

1. If we follow spec, it may cause legacy applications fail.

2. Other service provider in nio module are all loaded by system class
loader.

Any suggestions and comments?

Thanks!


--
Andrew Zhang
China Software Development Lab, IBM

Reply via email to