Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
Name: rv122619 Date: 07/29/2004 When we replace the System classloader without our own using the approved java.lang.class.loader method the VM fails to start. This is caused by the UnixFileSystem.list method constructing a String. The String construction is failing trying to find the system charset before the SystemClassloader is finished being constructed. This happens on most non-english locales. Specificly JA. This happens on Solaris as well as Linux. I have not been able to try this on Windows. Included are 3 source files and a config file. compile and run with the following script: echo "compiling" javac loader/src/com/jim/*.java jar cf loader.jar -C loader/src . mv loader.jar loader/dist /bigdisk/suwall/jdk1.5.0/bin/javac -source 1.4 test.java /bigdisk/suwall/jdk1.5.0/bin/jar cf test.jar *.class export LC_ALL=ja locale echo "" for x in /usr/j2re1.4.1_02/bin do ${x}/java -version ${x}/java -debug -cp "loader/dist/loader.jar" -Dsas.app.class.dirs="." -Djava.system.class.loader=com.jim.AppClassLoader test =com/jim/AppClassLoader.java======================================== package com.jim; import java.io.IOException; import java.io.File; import java.net.URL; import java.net.MalformedURLException; import java.net.URLStreamHandler; import java.util.Vector; import java.net.URLStreamHandlerFactory; import java.util.StringTokenizer; import sun.net.www.ParseUtil; public class AppClassLoader extends java.net.URLClassLoader { /** * The AppClassLoader is the start of the SAS Application level classloaders. * This classloader defines the location for the classes used by the application. * The system property "sas.app.class.dirs" points to a set of directories that will * be scanned for jar files. This acts much like the extensions classloader. The property * sas.app.class.path points to a list of classes or jars that actually define the application. * This acts much like the classpath and are prepended to the list of jars found using the * "sas.app.class.dirs" property. */ public AppClassLoader(ClassLoader parent) { super(getFileURLs("sas.app.class.dirs", "sas.app.class.path"), new ExtClassLoader(parent)); //$NON-NLS-1$ //$NON-NLS-2$ } /** * scans the System property for directories. Each directory is scanned for files. * Each file is then returned as an URL. This has the effect of added every jar and * zip in each directory to the list. This has the side effect of adding and sub-directory * as a directory of classes to the list. */ private static URL[] getFileURLs(String jarProperty, String pathProperty) { // create an array of path names from the webaf.class.path property File[] dirs = getDirs(jarProperty); File[] path = getPath(pathProperty); // translate these pathnames in URLs Vector urls = new Vector(); int i; // first do the path if it exists for(i=0;i<path.length;++i) { if (path[i] != null) urls.add(getFileURL(path[i])); } // next do the jar directories for (i = 0; i < dirs.length; i++) { String[] files = dirs[i].list(); if (files != null) { for (int j = 0; j < files.length; j++) { File f = new File(dirs[i], files[j]); urls.add(getFileURL(f)); } } } URL[] ua = new URL[urls.size()]; urls.copyInto(ua); return ua; } /** * scans the System property for a list of directories. */ private static File[] getDirs(String property) { String s = System.getProperty(property); File[] dirs; if (s != null) { StringTokenizer st = new StringTokenizer(s, File.pathSeparator); int count = st.countTokens(); dirs = new File[count]; for (int i = 0; i < count; i++) { dirs[i] = new File(st.nextToken()); } } else { dirs = new File[0]; } return dirs; } /** * scans the System property for a list of files. */ private static File[] getPath(String property) { String s = System.getProperty(property); File[] dirs; if (s != null) { StringTokenizer st = new StringTokenizer(s, File.pathSeparator); int count = st.countTokens(); dirs = new File[count]; for (int i = 0; i < count; i++) { dirs[i] = new File(st.nextToken()); } } else { dirs = new File[0]; } return dirs; } /** * Translated the passed in File into an URL. Handles spaces in file names. * @param file The File to be translated into an URL * @return URL The file location translated into an URL */ private static URL getFileURL(File file) { try { file = file.getCanonicalFile(); } catch (IOException e) {} try { return ParseUtil.fileToEncodedURL(file); } catch (MalformedURLException e) { // Should never happen since we specify the protocol... throw new InternalError(); } } /** * Appends the specified URL to the list of URLs to search for classes and resources. * * @param url the URL to be added to the search path of URLs **/ public void add(URL u) { addURL(u); } } =com/jim/ExtClassLoader.java=================================================== package com.jim; import java.io.IOException; import java.io.File; import java.net.URL; import java.net.MalformedURLException; import java.net.URLStreamHandler; import java.util.Vector; import java.net.URLStreamHandlerFactory; import java.io.FileInputStream; import java.io.BufferedReader; import java.io.FileReader; import java.io.InputStream; import java.io.FileNotFoundException; import java.text.MessageFormat; import java.util.ResourceBundle; import java.util.Locale; public class ExtClassLoader extends java.net.URLClassLoader { /* * The ExtClassLoader scans the normal extensions classloader * for a known set of URLs. These URLs are identified from the contents * of a config file. The default config is com.sas.app.JavaEXTs.config. * an alternate file will be used if it is speicified in the System property * "sas.java.config" */ public ExtClassLoader(ClassLoader parent) { super(getFilteredURLs(parent), null); // skip the extensions classloader } /** * getFileredURLs scans the extensions classloader for its known URLs and only uses * a subset as defined by the contents of JavaEXTs.config. The config file is a list of jar * names. Absolute names are not used. Each URL is scanned to determine if it points to * a jar named in the config file. Any matches are selected and returned by this method. * All jar names must be complete names. Fragments will not match. */ private static URL[] getFilteredURLs(ClassLoader parent) { ClassLoaderUtil clu = new ClassLoaderUtil(); Vector v = new Vector(); int num = 0; // read the config file. This handles finding the config via the System Property // first then looking near the class. String configLocation=null; try { configLocation = System.getProperty("sas.ext.config"); //$NON-NLS-1$ InputStream in=null; if (configLocation != null) { in=new FileInputStream(configLocation); } else { configLocation=clu.getConfigName(); in = clu.getConfig(); //if the input stream is null, then throw a FileNotFoundException like the user-specified //config strategy will throw and catch below to print out message. if (in==null) throw new FileNotFoundException(); } BufferedReader br=new BufferedReader(new java.io.InputStreamReader(in, "ISO_8859-1:1987")); boolean done = false; while(!done) { String line = br.readLine(); if (line == null) done = true; else { v.addElement(line); ++num; } } br.close(); } catch(FileNotFoundException e1) { //I'm having to do the ResourceBundle work manually since the Launcher jar shouldn't depend on any other jars. ResourceBundle resourceBundle=ResourceBundle.getBundle("com.sas.app.Resources", //$NON-NLS-1$ Locale.getDefault(), ExtClassLoader.class.getClassLoader()); MessageFormat format=new MessageFormat(resourceBundle.getString("ExtClassLoader.ConfigLocationError.txt")); //$NON-NLS-1$ Object[] messageArgs=new Object[1]; messageArgs[0]=configLocation; System.err.println(format.format(messageArgs)); } catch(IOException e2) { e2.printStackTrace(); } // grab the urls from the extensions classloader and see which ones match the jars from the // list in the config file. We prepend a slash to the jar name so we don't match partials. String[] filter = (String[])v.toArray(new String[num]); ClassLoader loader = parent.getParent(); // hope this is the extensions classloader if (loader instanceof java.net.URLClassLoader) { URL[] u = ((java.net.URLClassLoader)loader).getURLs(); v.removeAllElements(); int i; for(i=0;i<u.length;++i) { int j; for(j=0;j<filter.length;++j) { if (u[i].getFile().endsWith("/"+filter[j])) //$NON-NLS-1$ v.addElement(u[i]); } } return (URL[])v.toArray(new URL[0]); } return null; } } /** * ClassLoaderUtil is here only to load the config file as a resource. This allows the config to * reside inside the jar file. */ class ClassLoaderUtil { public ClassLoaderUtil() { } public String getConfigName() { return "JavaEXTs.config"; //$NON-NLS-1$ } public InputStream getConfig() { return getClass().getResourceAsStream(getConfigName()); } } =com/jim/JavaEXTs.config======================================== dnsns.jar ldapsec.jar localedata.jar sunjce_provider.jar =test.java================================================== public class test { public static void main(String[] args) { System.getProperties().list(System.out); System.out.println("test"); System.exit(0); } } ======================================================================
|