changeset 57754:8e10404eec8e

8236075: Minor bootstrap improvements Reviewed-by: mchung, alanb
author redestad
date Tue, 21 Jan 2020 13:28:15 +0100
parents 3ca4a8016584
children 146949f377a2
files src/hotspot/share/classfile/systemDictionary.cpp src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java src/java.base/share/classes/java/lang/ClassLoader.java src/java.base/share/classes/java/lang/System.java src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java src/java.base/share/classes/jdk/internal/util/StaticProperty.java src/java.base/unix/classes/java/lang/ClassLoaderHelper.java src/java.base/windows/classes/java/lang/ClassLoaderHelper.java test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java test/jdk/java/lang/ClassLoader/LibraryPathProperty.java
diffstat 10 files changed, 208 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Tue Jan 21 13:28:15 2020 +0100
@@ -1564,7 +1564,7 @@
   unsigned int d_hash = dictionary->compute_hash(name_h);
   check_constraints(d_hash, k, class_loader_h, true, CHECK);
 
-  // Register class just loaded with class loader (placed in Vector)
+  // Register class just loaded with class loader (placed in ArrayList)
   // Note we do this before updating the dictionary, as this can
   // fail with an OutOfMemoryError (if it does, we will *not* put this
   // class in the dictionary and will not update the class hierarchy).
--- a/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/java.base/macosx/classes/java/lang/ClassLoaderHelper.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,11 +32,6 @@
     private ClassLoaderHelper() {}
 
     /**
-     * Indicates, whether PATH env variable is allowed to contain quoted entries.
-     */
-    static final boolean allowsQuotedPathElements = false;
-
-    /**
      * Returns an alternate path name for the given file
      * such that if the original pathname did not exist, then the
      * file may be located at the alternate location.
@@ -50,4 +45,25 @@
         }
         return new File(name.substring(0, index) + ".jnilib");
     }
+
+    /**
+     * Parse a PATH env variable.
+     *
+     * Empty elements will be replaced by dot.
+     */
+    static String[] parsePath(String ldPath) {
+        char ps = File.pathSeparatorChar;
+        ArrayList<String> paths = new ArrayList<>();
+        int pathStart = 0;
+        int pathEnd;
+        while ((pathEnd = ldPath.indexOf(ps, pathStart)) >= 0) {
+            paths.add((pathStart < pathEnd) ?
+                    ldPath.substring(pathStart, pathEnd) : ".");
+            pathStart = pathEnd + 1;
+        }
+        int ldLen = ldPath.length();
+        paths.add((pathStart < ldLen) ?
+                ldPath.substring(pathStart, ldLen) : ".");
+        return paths.toArray(new String[paths.size()]);
+    }
 }
--- a/src/java.base/share/classes/java/lang/ClassLoader.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2019, Azul Systems, Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -40,20 +40,19 @@
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;
 import java.util.ArrayDeque;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Deque;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Hashtable;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Set;
 import java.util.Spliterator;
 import java.util.Spliterators;
-import java.util.Vector;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Supplier;
@@ -69,6 +68,7 @@
 import jdk.internal.ref.CleanerFactory;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
+import jdk.internal.util.StaticProperty;
 import sun.reflect.misc.ReflectUtil;
 import sun.security.util.SecurityConstants;
 
@@ -303,14 +303,14 @@
     private final ConcurrentHashMap<String, Object> parallelLockMap;
 
     // Maps packages to certs
-    private final Map <String, Certificate[]> package2certs;
+    private final ConcurrentHashMap<String, Certificate[]> package2certs;
 
     // Shared among all packages with unsigned classes
     private static final Certificate[] nocerts = new Certificate[0];
 
     // The classes loaded by this class loader. The only purpose of this table
     // is to keep the classes from being GC'ed until the loader is GC'ed.
-    private final Vector<Class<?>> classes = new Vector<>();
+    private final ArrayList<Class<?>> classes = new ArrayList<>();
 
     // The "default" domain. Set as the default ProtectionDomain on newly
     // created classes.
@@ -320,7 +320,9 @@
 
     // Invoked by the VM to record every loaded class with this loader.
     void addClass(Class<?> c) {
-        classes.addElement(c);
+        synchronized (classes) {
+            classes.add(c);
+        }
     }
 
     // The packages defined in this class loader.  Each package name is
@@ -378,14 +380,13 @@
         this.unnamedModule = new Module(this);
         if (ParallelLoaders.isRegistered(this.getClass())) {
             parallelLockMap = new ConcurrentHashMap<>();
-            package2certs = new ConcurrentHashMap<>();
             assertionLock = new Object();
         } else {
             // no finer-grained lock; lock on the classloader instance
             parallelLockMap = null;
-            package2certs = new Hashtable<>();
             assertionLock = this;
         }
+        this.package2certs = new ConcurrentHashMap<>();
         this.nameAndId = nameAndId(this);
     }
 
@@ -1135,18 +1136,8 @@
         if (cs != null) {
             certs = cs.getCertificates();
         }
-        Certificate[] pcerts = null;
-        if (parallelLockMap == null) {
-            synchronized (this) {
-                pcerts = package2certs.get(pname);
-                if (pcerts == null) {
-                    package2certs.put(pname, (certs == null? nocerts:certs));
-                }
-            }
-        } else {
-            pcerts = ((ConcurrentHashMap<String, Certificate[]>)package2certs).
-                putIfAbsent(pname, (certs == null? nocerts:certs));
-        }
+        certs = certs == null ? nocerts : certs;
+        Certificate[] pcerts = package2certs.putIfAbsent(pname, certs);
         if (pcerts != null && !compareCerts(pcerts, certs)) {
             throw new SecurityException("class \"" + name
                 + "\"'s signer information does not match signer information"
@@ -1158,13 +1149,10 @@
      * check to make sure the certs for the new class (certs) are the same as
      * the certs for the first class inserted in the package (pcerts)
      */
-    private boolean compareCerts(Certificate[] pcerts,
-                                 Certificate[] certs)
-    {
-        // certs can be null, indicating no certs.
-        if ((certs == null) || (certs.length == 0)) {
+    private boolean compareCerts(Certificate[] pcerts, Certificate[] certs) {
+        // empty array fast-path
+        if (certs.length == 0)
             return pcerts.length == 0;
-        }
 
         // the length must be the same at this point
         if (certs.length != pcerts.length)
@@ -2005,17 +1993,6 @@
         return scl;
     }
 
-    /*
-     * Initialize default paths for native libraries search.
-     * Must be done early as JDK may load libraries during bootstrap.
-     *
-     * @see java.lang.System#initPhase1
-     */
-    static void initLibraryPaths() {
-        usr_paths = initializePath("java.library.path");
-        sys_paths = initializePath("sun.boot.library.path");
-    }
-
     // Returns true if the specified class loader can be found in this class
     // loader's delegation chain.
     boolean isAncestor(ClassLoader cl) {
@@ -2570,59 +2547,17 @@
         static native void unload(String name, boolean isBuiltin, long handle);
     }
 
-    // The paths searched for libraries
-    private static String usr_paths[];
-    private static String sys_paths[];
-
-    private static String[] initializePath(String propName) {
-        String ldPath = System.getProperty(propName, "");
-        int ldLen = ldPath.length();
-        char ps = File.pathSeparatorChar;
-        int psCount = 0;
-
-        if (ClassLoaderHelper.allowsQuotedPathElements &&
-            ldPath.indexOf('\"') >= 0) {
-            // First, remove quotes put around quoted parts of paths.
-            // Second, use a quotation mark as a new path separator.
-            // This will preserve any quoted old path separators.
-            char[] buf = new char[ldLen];
-            int bufLen = 0;
-            for (int i = 0; i < ldLen; ++i) {
-                char ch = ldPath.charAt(i);
-                if (ch == '\"') {
-                    while (++i < ldLen &&
-                        (ch = ldPath.charAt(i)) != '\"') {
-                        buf[bufLen++] = ch;
-                    }
-                } else {
-                    if (ch == ps) {
-                        psCount++;
-                        ch = '\"';
-                    }
-                    buf[bufLen++] = ch;
-                }
-            }
-            ldPath = new String(buf, 0, bufLen);
-            ldLen = bufLen;
-            ps = '\"';
-        } else {
-            for (int i = ldPath.indexOf(ps); i >= 0;
-                 i = ldPath.indexOf(ps, i + 1)) {
-                psCount++;
-            }
-        }
-
-        String[] paths = new String[psCount + 1];
-        int pathStart = 0;
-        for (int j = 0; j < psCount; ++j) {
-            int pathEnd = ldPath.indexOf(ps, pathStart);
-            paths[j] = (pathStart < pathEnd) ?
-                ldPath.substring(pathStart, pathEnd) : ".";
-            pathStart = pathEnd + 1;
-        }
-        paths[psCount] = (pathStart < ldLen) ?
-            ldPath.substring(pathStart, ldLen) : ".";
-        return paths;
+    /**
+     * Holds system and user library paths derived from the
+     * {@code java.library.path} and {@code sun.boot.library.path} system
+     * properties. The system properties are eagerly read at bootstrap, then
+     * lazily parsed on first use to avoid initialization ordering issues.
+     */
+    private static class LibraryPaths {
+        static final String[] USER =
+                ClassLoaderHelper.parsePath(StaticProperty.javaLibraryPath());
+        static final String[] SYS =
+                ClassLoaderHelper.parsePath(StaticProperty.sunBootLibraryPath());
     }
 
     // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
@@ -2630,8 +2565,6 @@
                             boolean isAbsolute) {
         ClassLoader loader =
             (fromClass == null) ? null : fromClass.getClassLoader();
-        assert sys_paths != null : "should be initialized at this point";
-        assert usr_paths != null : "should be initialized at this point";
 
         if (isAbsolute) {
             if (loadLibrary0(fromClass, new File(name))) {
@@ -2653,8 +2586,8 @@
                 throw new UnsatisfiedLinkError("Can't load " + libfilename);
             }
         }
-        for (String sys_path : sys_paths) {
-            File libfile = new File(sys_path, System.mapLibraryName(name));
+        for (String sysPath : LibraryPaths.SYS) {
+            File libfile = new File(sysPath, System.mapLibraryName(name));
             if (loadLibrary0(fromClass, libfile)) {
                 return;
             }
@@ -2664,8 +2597,8 @@
             }
         }
         if (loader != null) {
-            for (String usr_path : usr_paths) {
-                File libfile = new File(usr_path, System.mapLibraryName(name));
+            for (String userPath : LibraryPaths.USER) {
+                File libfile = new File(userPath, System.mapLibraryName(name));
                 if (loadLibrary0(fromClass, libfile)) {
                     return;
                 }
@@ -2677,7 +2610,7 @@
         }
         // Oops, it failed
         throw new UnsatisfiedLinkError("no " + name +
-            " in java.library.path: " + Arrays.toString(usr_paths));
+            " in java.library.path: " + Arrays.toString(LibraryPaths.USER));
     }
 
     private static native String findBuiltinLib(String name);
--- a/src/java.base/share/classes/java/lang/System.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/java.base/share/classes/java/lang/System.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2043,8 +2043,6 @@
         // register shared secrets
         setJavaLangAccess();
 
-        ClassLoader.initLibraryPaths();
-
         // Subsystems that are invoked during initialization can invoke
         // VM.isBooted() in order to avoid doing things that should
         // wait until the VM is fully initialized. The initialization level
--- a/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -198,22 +198,23 @@
      * types in the module visible.
      */
     public void loadModule(ModuleReference mref) {
-        String mn = mref.descriptor().name();
+        ModuleDescriptor descriptor = mref.descriptor();
+        String mn = descriptor.name();
         if (nameToModule.putIfAbsent(mn, mref) != null) {
             throw new InternalError(mn + " already defined to this loader");
         }
 
         LoadedModule loadedModule = new LoadedModule(this, mref);
-        for (String pn : mref.descriptor().packages()) {
+        for (String pn : descriptor.packages()) {
             LoadedModule other = packageToModule.putIfAbsent(pn, loadedModule);
             if (other != null) {
                 throw new InternalError(pn + " in modules " + mn + " and "
-                                        + other.mref().descriptor().name());
+                                        + other.name());
             }
         }
 
         // clear resources cache if VM is already initialized
-        if (VM.isModuleSystemInited() && resourceCache != null) {
+        if (resourceCache != null && VM.isModuleSystemInited()) {
             resourceCache = null;
         }
     }
@@ -408,8 +409,11 @@
         SoftReference<Map<String, List<URL>>> ref = this.resourceCache;
         Map<String, List<URL>> map = (ref != null) ? ref.get() : null;
         if (map == null) {
-            map = new ConcurrentHashMap<>();
-            this.resourceCache = new SoftReference<>(map);
+            // only cache resources after VM is fully initialized
+            if (VM.isModuleSystemInited()) {
+                map = new ConcurrentHashMap<>();
+                this.resourceCache = new SoftReference<>(map);
+            }
         } else {
             List<URL> urls = map.get(name);
             if (urls != null)
@@ -444,7 +448,7 @@
         }
 
         // only cache resources after VM is fully initialized
-        if (VM.isModuleSystemInited()) {
+        if (map != null) {
             map.putIfAbsent(name, urls);
         }
 
--- a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package jdk.internal.util;
 
+import java.util.Properties;
+
 /**
  * System Property access for internal use only.
  * Read-only access to System property values initialized during Phase 1
@@ -38,22 +40,41 @@
 
     // The class static initialization is triggered to initialize these final
     // fields during init Phase 1 and before a security manager is set.
-    private static final String JAVA_HOME = initProperty("java.home");
-    private static final String USER_HOME = initProperty("user.home");
-    private static final String USER_DIR  = initProperty("user.dir");
-    private static final String USER_NAME = initProperty("user.name");
-    private static final String JDK_SERIAL_FILTER = System.getProperty("jdk.serialFilter");
+    private static final String JAVA_HOME;
+    private static final String USER_HOME;
+    private static final String USER_DIR;
+    private static final String USER_NAME;
+    private static final String JAVA_LIBRARY_PATH;
+    private static final String SUN_BOOT_LIBRARY_PATH;
+    private static final String JDK_SERIAL_FILTER;
 
     private StaticProperty() {}
 
-    private static String initProperty(String key) {
-        String v = System.getProperty(key);
+    static {
+        Properties props = System.getProperties();
+        JAVA_HOME = getProperty(props, "java.home");
+        USER_HOME = getProperty(props, "user.home");
+        USER_DIR  = getProperty(props, "user.dir");
+        USER_NAME = getProperty(props, "user.name");
+        JAVA_LIBRARY_PATH = getProperty(props, "java.library.path", "");
+        SUN_BOOT_LIBRARY_PATH = getProperty(props, "sun.boot.library.path", "");
+        JDK_SERIAL_FILTER = getProperty(props, "jdk.serialFilter", null);
+    }
+
+    private static String getProperty(Properties props, String key) {
+        String v = props.getProperty(key);
         if (v == null) {
             throw new InternalError("null property: " + key);
         }
         return v;
     }
 
+    private static String getProperty(Properties props, String key,
+                                      String defaultVal) {
+        String v = props.getProperty(key);
+        return (v == null) ? defaultVal : v;
+    }
+
     /**
      * Return the {@code java.home} system property.
      *
@@ -107,6 +128,33 @@
     }
 
     /**
+     * Return the {@code java.library.path} system property.
+     *
+     * <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
+     * in this method. The caller of this method should take care to ensure
+     * that the returned property is not made accessible to untrusted code.</strong>
+     *
+     * @return the {@code java.library.path} system property
+     */
+    public static String javaLibraryPath() {
+        return JAVA_LIBRARY_PATH;
+    }
+
+    /**
+     * Return the {@code sun.boot.library.path} system property.
+     *
+     * <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
+     * in this method. The caller of this method should take care to ensure
+     * that the returned property is not made accessible to untrusted code.</strong>
+     *
+     * @return the {@code sun.boot.library.path} system property
+     */
+    public static String sunBootLibraryPath() {
+        return SUN_BOOT_LIBRARY_PATH;
+    }
+
+
+    /**
      * Return the {@code jdk.serialFilter} system property.
      *
      * <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
--- a/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/java.base/unix/classes/java/lang/ClassLoaderHelper.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,17 +26,13 @@
 package java.lang;
 
 import java.io.File;
+import java.util.ArrayList;
 
 class ClassLoaderHelper {
 
     private ClassLoaderHelper() {}
 
     /**
-     * Indicates, whether PATH env variable is allowed to contain quoted entries.
-     */
-    static final boolean allowsQuotedPathElements = false;
-
-    /**
      * Returns an alternate path name for the given file
      * such that if the original pathname did not exist, then the
      * file may be located at the alternate location.
@@ -45,4 +41,25 @@
     static File mapAlternativeName(File lib) {
         return null;
     }
+
+    /**
+     * Parse a PATH env variable.
+     *
+     * Empty elements will be replaced by dot.
+     */
+    static String[] parsePath(String ldPath) {
+        char ps = File.pathSeparatorChar;
+        ArrayList<String> paths = new ArrayList<>();
+        int pathStart = 0;
+        int pathEnd;
+        while ((pathEnd = ldPath.indexOf(ps, pathStart)) >= 0) {
+            paths.add((pathStart < pathEnd) ?
+                    ldPath.substring(pathStart, pathEnd) : ".");
+            pathStart = pathEnd + 1;
+        }
+        int ldLen = ldPath.length();
+        paths.add((pathStart < ldLen) ?
+                ldPath.substring(pathStart, ldLen) : ".");
+        return paths.toArray(new String[paths.size()]);
+    }
 }
--- a/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/src/java.base/windows/classes/java/lang/ClassLoaderHelper.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,11 +32,6 @@
     private ClassLoaderHelper() {}
 
     /**
-     * Indicates, whether PATH env variable is allowed to contain quoted entries.
-     */
-    static final boolean allowsQuotedPathElements = true;
-
-    /**
      * Returns an alternate path name for the given file
      * such that if the original pathname did not exist, then the
      * file may be located at the alternate location.
@@ -45,4 +40,59 @@
     static File mapAlternativeName(File lib) {
         return null;
     }
+
+    /**
+     * Parse a PATH env variable. Windows allows quoted elements in a PATH,
+     * so special care needs to be taken.
+     *
+     * Empty elements will be replaced by dot.
+     */
+    static String[] parsePath(String ldPath) {
+        int ldLen = ldPath.length();
+        char ps = File.pathSeparatorChar;
+        int psCount = 0;
+
+        if (ldPath.indexOf('\"') >= 0) {
+            // First, remove quotes put around quoted parts of paths.
+            // Second, use a quotation mark as a new path separator.
+            // This will preserve any quoted old path separators.
+            char[] buf = new char[ldLen];
+            int bufLen = 0;
+            for (int i = 0; i < ldLen; ++i) {
+                char ch = ldPath.charAt(i);
+                if (ch == '\"') {
+                    while (++i < ldLen &&
+                            (ch = ldPath.charAt(i)) != '\"') {
+                        buf[bufLen++] = ch;
+                    }
+                } else {
+                    if (ch == ps) {
+                        psCount++;
+                        ch = '\"';
+                    }
+                    buf[bufLen++] = ch;
+                }
+            }
+            ldPath = new String(buf, 0, bufLen);
+            ldLen = bufLen;
+            ps = '\"';
+        } else {
+            for (int i = ldPath.indexOf(ps); i >= 0;
+                 i = ldPath.indexOf(ps, i + 1)) {
+                psCount++;
+            }
+        }
+
+        String[] paths = new String[psCount + 1];
+        int pathStart = 0;
+        for (int j = 0; j < psCount; ++j) {
+            int pathEnd = ldPath.indexOf(ps, pathStart);
+            paths[j] = (pathStart < pathEnd) ?
+                    ldPath.substring(pathStart, pathEnd) : ".";
+            pathStart = pathEnd + 1;
+        }
+        paths[psCount] = (pathStart < ldLen) ?
+                ldPath.substring(pathStart, ldLen) : ".";
+        return paths;
+    }
 }
--- a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java	Tue Jan 21 13:28:15 2020 +0100
@@ -62,7 +62,7 @@
     public static WhiteBox wb = WhiteBox.getWhiteBox();
     private static String[] SAInstanceKlassNames = new String[] {
                                                 "java.lang.Object",
-                                                "java.util.Vector",
+                                                "java.util.ArrayList",
                                                 "java.lang.String",
                                                 "java.lang.Thread",
                                                 "java.lang.Byte"
--- a/test/jdk/java/lang/ClassLoader/LibraryPathProperty.java	Thu Jan 16 18:04:23 2020 +0100
+++ b/test/jdk/java/lang/ClassLoader/LibraryPathProperty.java	Tue Jan 21 13:28:15 2020 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,8 @@
 
 /*
  * @test
- * @bug 8067951
- * @summary Unit test for internal ClassLoader#initializePath().
+ * @bug 8067951 8236075
+ * @summary Unit test for internal ClassLoaderHelper#parsePath().
  *          Quoted entries should get unquoted on Windows.
  *          Empty entries should be replaced with dot.
  * @library /test/lib
@@ -40,14 +40,12 @@
 
 public class LibraryPathProperty {
 
-    static final String propName = "test.property.name";
     static final String SP = File.pathSeparator;
     static Method method;
 
     public static void main(String[] args) throws Throwable {
-        method = ClassLoader.class
-                .getDeclaredMethod("initializePath",
-                                   String.class);
+        Class<?> klass = Class.forName("java.lang.ClassLoaderHelper");
+        method = klass.getDeclaredMethod("parsePath", String.class);
         method.setAccessible(true);
 
         test("", ".");
@@ -74,8 +72,7 @@
     }
 
     static void test(String s, String... expected) throws Throwable {
-        System.setProperty(propName, s);
-        String[] res = (String[])method.invoke(null, propName);
+        String[] res = (String[])method.invoke(null, s);
         if (!Arrays.asList(res).equals(Arrays.asList(expected))) {
             throw new RuntimeException("Parsing [" + s + "] " +
                     " result " + Arrays.asList(res) +