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