< prev index next >

src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java

Print this page
*** 49,17 ***
--- 49,19 ---
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.NoSuchElementException;
  import java.util.Optional;
+ import java.util.Set;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.function.Function;
  import java.util.jar.Attributes;
  import java.util.jar.Manifest;
  import java.util.stream.Stream;
  
  import jdk.internal.access.SharedSecrets;
+ import jdk.internal.misc.CDS;
  import jdk.internal.misc.VM;
  import jdk.internal.module.ModulePatcher.PatchedModuleReader;
  import jdk.internal.module.Resources;
  import jdk.internal.vm.annotation.Stable;
  import sun.security.util.LazyCodeSourcePermissionCollection;

*** 104,10 ***
--- 106,16 ---
      private final BuiltinClassLoader parent;
  
      // the URL class path, or null if there is no class path
      private @Stable URLClassPath ucp;
  
+     private Set<String> negativeLookupCache;
+     private Map<String, Class<? extends Object>> positiveLookupCache;
+ 
+     public boolean useNegativeCache = false;
+     public boolean usePositiveCache = false;
+ 
      /**
       * A module defined/loaded by a built-in class loader.
       *
       * A LoadedModule encapsulates a ModuleReference along with its CodeSource
       * URL to avoid needing to create this URL when defining classes.

*** 196,10 ***
--- 204,12 ---
          this.parent = parent;
          this.ucp = ucp;
  
          this.nameToModule = new ConcurrentHashMap<>(32);
          this.moduleToReader = new ConcurrentHashMap<>();
+         this.negativeLookupCache = ConcurrentHashMap.newKeySet();
+         this.positiveLookupCache = new ConcurrentHashMap<>();
      }
  
      /**
       * Appends to the given file path to the class path.
       */

*** 634,13 ***
       */
      @Override
      protected Class<?> loadClass(String cn, boolean resolve)
          throws ClassNotFoundException
      {
          Class<?> c = loadClassOrNull(cn, resolve);
!         if (c == null)
              throw new ClassNotFoundException(cn);
          return c;
      }
  
      /**
       * A variation of {@code loadClass} to load a class with the specified
--- 644,19 ---
       */
      @Override
      protected Class<?> loadClass(String cn, boolean resolve)
          throws ClassNotFoundException
      {
+         if (useNegativeCache && checkNegativeLookupCache(cn)) {
+             throw new ClassNotFoundException(cn);
+         }
          Class<?> c = loadClassOrNull(cn, resolve);
!         if (c == null) {
+             addToNegativeLookupCache(cn);
              throw new ClassNotFoundException(cn);
+         }
+ 
          return c;
      }
  
      /**
       * A variation of {@code loadClass} to load a class with the specified

*** 1083,6 ***
--- 1099,53 ---
      // Called from VM only, during -Xshare:dump
      private void resetArchivedStates() {
          ucp = null;
          resourceCache = null;
      }
+ 
+     public boolean checkNegativeLookupCache(String className) {
+         return negativeLookupCache.contains(className);
+     }
+ 
+     public void addToNegativeLookupCache(String className) {
+         negativeLookupCache.add(className);
+     }
+ 
+     public String negativeLookupCacheContents() {
+         String[] contents = negativeLookupCache.toArray(new String[]{});
+         StringBuilder builder = new StringBuilder();
+         if (contents.length != 0) {
+             for (String name: contents) {
+                 if (builder.length() != 0) {
+                     builder.append(" ");
+                 }
+                 builder.append(name);
+             }
+             return builder.toString();
+         } else {
+             return null;
+         }
+     }
+ 
+     public void generateNegativeLookupCache(String contents) {
+         String[] tokens = contents.split(" ");
+         if (tokens.length > 0) {
+             for (String token : tokens) {
+                 negativeLookupCache.add(token);
+             }
+             useNegativeCache = true;
+         }
+     }
+ 
+     public Class<?> checkPositiveLookupCache(String className) {
+         return positiveLookupCache.get(className);
+     }
+ 
+     public void generatePositiveLookupCache(Class<?>[] cls) {
+         if (cls.length > 0) {
+             for (Class<?> c : cls) {
+                 positiveLookupCache.put(c.getName(), c);
+             }
+             usePositiveCache = true;
+         }
+     }
  }
< prev index next >