From 8306ccd8ecec9036a66d09263ab4da05347f9979 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 29 Dec 2014 13:56:05 +0300 Subject: [PATCH] Preloader: extract nested classes to top-level --- .../jet/preloading/ClassHandler.java | 32 ++++ .../jet/preloading/ClassPreloadingUtils.java | 159 +----------------- .../preloading/MemoryBasedClassLoader.java | 136 +++++++++++++++ .../jetbrains/jet/preloading/Preloader.java | 2 +- .../jet/preloading/ResourceData.java | 62 +++++++ 5 files changed, 232 insertions(+), 159 deletions(-) create mode 100644 compiler/preloader/src/org/jetbrains/jet/preloading/ClassHandler.java create mode 100644 compiler/preloader/src/org/jetbrains/jet/preloading/MemoryBasedClassLoader.java create mode 100644 compiler/preloader/src/org/jetbrains/jet/preloading/ResourceData.java diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/ClassHandler.java b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassHandler.java new file mode 100644 index 00000000000..c1d8d12ff5f --- /dev/null +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassHandler.java @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.preloading; + +import java.io.File; + +@SuppressWarnings("UnusedParameters") +public abstract class ClassHandler { + public byte[] instrument(String resourceName, byte[] data) { + return data; + } + + public void beforeDefineClass(String name, int sizeInBytes) {} + public void afterDefineClass(String name) {} + + public void beforeLoadJar(File jarFile) {} + public void afterLoadJar(File jarFile) {} +} diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java index 10882d7ebcb..421e472db83 100644 --- a/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/ClassPreloadingUtils.java @@ -17,10 +17,6 @@ package org.jetbrains.jet.preloading; import java.io.*; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; import java.util.*; import java.util.jar.Attributes; import java.util.jar.JarFile; @@ -30,19 +26,6 @@ import java.util.zip.ZipInputStream; @SuppressWarnings("unchecked") public class ClassPreloadingUtils { - - public static abstract class ClassHandler { - public byte[] instrument(String resourceName, byte[] data) { - return data; - } - - public void beforeDefineClass(String name, int sizeInBytes) {} - public void afterDefineClass(String name) {} - - public void beforeLoadJar(File jarFile) {} - public void afterLoadJar(File jarFile) {} - } - /** * Creates a class loader that loads all classes from {@code jarFiles} into memory to make loading faster (avoid skipping through zip archives). * @@ -70,7 +53,7 @@ public class ClassPreloadingUtils { parentClassLoader = preloadClasses(classpath, classCountEstimation, parentClassLoader, null, handler); } - return createMemoryBasedClassLoader(parentClassLoader, entries, handler, classesToLoadByParent); + return new MemoryBasedClassLoader(classesToLoadByParent, parentClassLoader, entries, handler); } public static ClassLoader preloadClasses( @@ -116,109 +99,6 @@ public class ClassPreloadingUtils { return classpath; } - private static ClassLoader createMemoryBasedClassLoader( - final ClassLoader parent, - final Map preloadedResources, - final ClassHandler handler, - final ClassCondition classesToLoadByParent - ) { - return new ClassLoader(null) { - @Override - public Class loadClass(String name) throws ClassNotFoundException { - if (classesToLoadByParent != null && classesToLoadByParent.accept(name)) { - if (parent == null) { - return super.loadClass(name); - } - - try { - return parent.loadClass(name); - } - catch (ClassNotFoundException e) { - return super.loadClass(name); - } - } - - // Look in this class loader and then in the parent one - Class aClass = super.loadClass(name); - if (aClass == null) { - if (parent == null) { - throw new ClassNotFoundException("Class not available in preloader: " + name); - } - return parent.loadClass(name); - } - return aClass; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - String internalName = name.replace('.', '/').concat(".class"); - Object resources = preloadedResources.get(internalName); - if (resources == null) return null; - - ResourceData resourceData = resources instanceof ResourceData - ? ((ResourceData) resources) - : ((List) resources).get(0); - - int sizeInBytes = resourceData.bytes.length; - if (handler != null) { - handler.beforeDefineClass(name, sizeInBytes); - } - - Class definedClass = defineClass(name, resourceData.bytes, 0, sizeInBytes); - - if (handler != null) { - handler.afterDefineClass(name); - } - - return definedClass; - } - - @Override - public URL getResource(String name) { - URL resource = super.getResource(name); - if (resource == null && parent != null) { - return parent.getResource(name); - } - return resource; - } - - @Override - protected URL findResource(String name) { - Enumeration resources = findResources(name); - return resources.hasMoreElements() ? resources.nextElement() : null; - } - - @Override - public Enumeration getResources(String name) throws IOException { - Enumeration resources = super.getResources(name); - if (!resources.hasMoreElements() && parent != null) { - return parent.getResources(name); - } - return resources; - } - - @Override - protected Enumeration findResources(String name) { - Object resources = preloadedResources.get(name); - if (resources == null) { - return Collections.enumeration(Collections.emptyList()); - } - else if (resources instanceof ResourceData) { - return Collections.enumeration(Collections.singletonList(((ResourceData) resources).getURL())); - } - else { - assert resources instanceof ArrayList : name; - List resourceDatas = (ArrayList) resources; - List urls = new ArrayList(resourceDatas.size()); - for (ResourceData data : resourceDatas) { - urls.add(data.getURL()); - } - return Collections.enumeration(urls); - } - } - }; - } - /** * @return a map of name to resources. Each value is either a ResourceData if there's only one instance (in the vast majority of cases) * or a non-empty ArrayList of ResourceData if there's many @@ -299,41 +179,4 @@ public class ClassPreloadingUtils { return resources; } - - private static final class ResourceData { - private final File jarFile; - private final String resourceName; - private final byte[] bytes; - - public ResourceData(File jarFile, String resourceName, byte[] bytes) { - this.jarFile = jarFile; - this.resourceName = resourceName; - this.bytes = bytes; - } - - public URL getURL() { - try { - String path = "file:" + jarFile + "!/" + resourceName; - return new URL("jar", null, 0, path, new URLStreamHandler() { - @Override - protected URLConnection openConnection(URL u) throws IOException { - return new URLConnection(u) { - @Override - public void connect() throws IOException {} - - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(bytes); - } - }; - } - }); - } - catch (MalformedURLException e) { - e.printStackTrace(); - return null; - } - } - - } } diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/MemoryBasedClassLoader.java b/compiler/preloader/src/org/jetbrains/jet/preloading/MemoryBasedClassLoader.java new file mode 100644 index 00000000000..32a6ce03f5d --- /dev/null +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/MemoryBasedClassLoader.java @@ -0,0 +1,136 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.preloading; + +import java.io.IOException; +import java.net.URL; +import java.util.*; + +@SuppressWarnings("unchecked") +public class MemoryBasedClassLoader extends ClassLoader { + private final ClassCondition classesToLoadByParent; + private final ClassLoader parent; + private final Map preloadedResources; + private final ClassHandler handler; + + public MemoryBasedClassLoader( + ClassCondition classesToLoadByParent, + ClassLoader parent, + Map preloadedResources, + ClassHandler handler + ) { + super(null); + this.classesToLoadByParent = classesToLoadByParent; + this.parent = parent; + this.preloadedResources = preloadedResources; + this.handler = handler; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (classesToLoadByParent != null && classesToLoadByParent.accept(name)) { + if (parent == null) { + return super.loadClass(name); + } + + try { + return parent.loadClass(name); + } + catch (ClassNotFoundException e) { + return super.loadClass(name); + } + } + + // Look in this class loader and then in the parent one + Class aClass = super.loadClass(name); + if (aClass == null) { + if (parent == null) { + throw new ClassNotFoundException("Class not available in preloader: " + name); + } + return parent.loadClass(name); + } + return aClass; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + String internalName = name.replace('.', '/').concat(".class"); + Object resources = preloadedResources.get(internalName); + if (resources == null) return null; + + ResourceData resourceData = resources instanceof ResourceData + ? ((ResourceData) resources) + : ((List) resources).get(0); + + int sizeInBytes = resourceData.bytes.length; + if (handler != null) { + handler.beforeDefineClass(name, sizeInBytes); + } + + Class definedClass = defineClass(name, resourceData.bytes, 0, sizeInBytes); + + if (handler != null) { + handler.afterDefineClass(name); + } + + return definedClass; + } + + @Override + public URL getResource(String name) { + URL resource = super.getResource(name); + if (resource == null && parent != null) { + return parent.getResource(name); + } + return resource; + } + + @Override + protected URL findResource(String name) { + Enumeration resources = findResources(name); + return resources.hasMoreElements() ? resources.nextElement() : null; + } + + @Override + public Enumeration getResources(String name) throws IOException { + Enumeration resources = super.getResources(name); + if (!resources.hasMoreElements() && parent != null) { + return parent.getResources(name); + } + return resources; + } + + @Override + protected Enumeration findResources(String name) { + Object resources = preloadedResources.get(name); + if (resources == null) { + return Collections.enumeration(Collections.emptyList()); + } + else if (resources instanceof ResourceData) { + return Collections.enumeration(Collections.singletonList(((ResourceData) resources).getURL())); + } + else { + assert resources instanceof ArrayList : "Resource map should contain ResourceData or ArrayList: " + name; + List resourceDatas = (ArrayList) resources; + List urls = new ArrayList(resourceDatas.size()); + for (ResourceData data : resourceDatas) { + urls.add(data.getURL()); + } + return Collections.enumeration(urls); + } + } +} diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java b/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java index df851fbb586..3c8e2ed789d 100644 --- a/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/Preloader.java @@ -186,7 +186,7 @@ public class Preloader { System.exit(1); } - private static class Handler extends ClassPreloadingUtils.ClassHandler { + private static class Handler extends ClassHandler { public void done() {} } } diff --git a/compiler/preloader/src/org/jetbrains/jet/preloading/ResourceData.java b/compiler/preloader/src/org/jetbrains/jet/preloading/ResourceData.java new file mode 100644 index 00000000000..b0f3d044681 --- /dev/null +++ b/compiler/preloader/src/org/jetbrains/jet/preloading/ResourceData.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.preloading; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; + +public final class ResourceData { + public final File jarFile; + public final String resourceName; + public final byte[] bytes; + + public ResourceData(File jarFile, String resourceName, byte[] bytes) { + this.jarFile = jarFile; + this.resourceName = resourceName; + this.bytes = bytes; + } + + public URL getURL() { + try { + String path = "file:" + jarFile + "!/" + resourceName; + return new URL("jar", null, 0, path, new URLStreamHandler() { + @Override + protected URLConnection openConnection(URL u) throws IOException { + return new URLConnection(u) { + @Override + public void connect() throws IOException {} + + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(bytes); + } + }; + } + }); + } + catch (MalformedURLException e) { + e.printStackTrace(); + return null; + } + } +}