Preloader for command-line compiler
This commit is contained in:
Generated
+1
@@ -26,6 +26,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/js/js.tests/js.tests.iml" filepath="$PROJECT_DIR$/js/js.tests/js.tests.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js/js.translator/js.translator.iml" filepath="$PROJECT_DIR$/js/js.translator/js.translator.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" filepath="$PROJECT_DIR$/jps-plugin/kannotator-jps-plugin-test/kannotator-jps-plugin-test.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/preloader/preloader.iml" filepath="$PROJECT_DIR$/compiler/preloader/preloader.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/runtime/runtime.iml" filepath="$PROJECT_DIR$/runtime/runtime.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/util/util.iml" filepath="$PROJECT_DIR$/compiler/util/util.iml" />
|
||||
</modules>
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
<dirset refid="compilerSources.dirset"/>
|
||||
</path>
|
||||
|
||||
<path id="preloaderSources.path">
|
||||
<dirset dir="compiler/preloader/src"/>
|
||||
</path>
|
||||
|
||||
<macrodef name="cleandir">
|
||||
<attribute name="dir"/>
|
||||
|
||||
@@ -236,15 +240,36 @@
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<target name="preloader">
|
||||
<cleandir dir="${output}/classes/preloader"/>
|
||||
<javac destdir="${output}/classes/preloader" debug="true" debuglevel="lines,vars,source" includeAntRuntime="false">
|
||||
<src refid="preloaderSources.path"/>
|
||||
</javac>
|
||||
|
||||
<jar jarfile="${kotlin-home}/lib/kotlin-preloader.jar">
|
||||
<fileset dir="${output}/classes/preloader"/>
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="JetBrains"/>
|
||||
|
||||
<attribute name="Implementation-Vendor" value="JetBrains"/>
|
||||
<attribute name="Implementation-Title" value="Kotlin Preloader"/>
|
||||
<attribute name="Implementation-Version" value="${build.number}"/>
|
||||
|
||||
<attribute name="Main-Class" value="org.jetbrains.jet.preloading.Preloader"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<macrodef name="pack_compiler">
|
||||
<attribute name="jarfile"/>
|
||||
<attribute name="compress" default="true"/>
|
||||
|
||||
|
||||
<sequential>
|
||||
<jar jarfile="@{jarfile}" compress="@{compress}">
|
||||
<fileset dir="${output}/classes/compiler"/>
|
||||
<fileset dir="${basedir}/compiler/frontend/src" includes="jet/**"/>
|
||||
|
||||
|
||||
<zipgroupfileset dir="${basedir}/lib" includes="*.jar"/>
|
||||
<zipgroupfileset dir="${basedir}/ideaSDK/core" includes="*.jar" excludes="util.jar"/>
|
||||
<zipgroupfileset dir="${basedir}/ideaSDK/lib" includes="jna-utils.jar"/>
|
||||
@@ -252,14 +277,14 @@
|
||||
<zipgroupfileset dir="${basedir}/js/js.translator/lib" includes="*.jar"/>
|
||||
<zipgroupfileset dir="${basedir}/dependencies" includes="jline.jar"/>
|
||||
<zipgroupfileset dir="${basedir}/dependencies" includes="jetbrains-asm-analysis-4.0.jar"/>
|
||||
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="JetBrains"/>
|
||||
|
||||
|
||||
<attribute name="Implementation-Vendor" value="JetBrains"/>
|
||||
<attribute name="Implementation-Title" value="Kotlin Compiler"/>
|
||||
<attribute name="Implementation-Version" value="${build.number}"/>
|
||||
|
||||
|
||||
<attribute name="Main-Class" value="org.jetbrains.jet.cli.jvm.K2JVMCompiler"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
@@ -517,13 +542,13 @@
|
||||
</target>
|
||||
|
||||
<target name="dist"
|
||||
depends="clean,init,prepareDist,compileGenerators,invokeGenerators,compiler,compilerSources,antTools,jdkAnnotations,annotationsExt,runtime,jslib,j2kConverter"/>
|
||||
depends="clean,init,prepareDist,compileGenerators,invokeGenerators,preloader,compiler,compilerSources,antTools,jdkAnnotations,annotationsExt,runtime,jslib,j2kConverter"/>
|
||||
|
||||
<target name="dist_quick"
|
||||
depends="clean,init,prepareDist,compiler_quick,antTools,jdkAnnotations,annotationsExt,runtime,jslib,j2kConverter"/>
|
||||
depends="clean,init,prepareDist,compileGenerators,invokeGenerators,preloader,compiler_quick,antTools,jdkAnnotations,annotationsExt,runtime,jslib,j2kConverter"/>
|
||||
|
||||
<target name="dist_quick_compiler_only"
|
||||
depends="init,prepareDist,compiler_quick"/>
|
||||
depends="init,prepareDist,preloader,compiler_quick"/>
|
||||
|
||||
<target name="zip" depends="dist">
|
||||
<zip destfile="${output}/${output.name}.zip">
|
||||
|
||||
@@ -81,5 +81,5 @@ CPSELECT="-cp "
|
||||
"${JAVACMD:=java}" \
|
||||
$JAVA_OPTS \
|
||||
"${java_args[@]}" \
|
||||
${CPSELECT}"${KOTLIN_HOME}/lib/kotlin-compiler.jar" \
|
||||
org.jetbrains.jet.cli.js.K2JSCompiler "$@"
|
||||
${CPSELECT}"${KOTLIN_HOME}/lib/kotlin-preloader.jar" \
|
||||
org.jetbrains.jet.preloading.Preloader "${KOTLIN_HOME}/lib/kotlin-compiler.jar" org.jetbrains.jet.cli.js.K2JSCompiler 4096 "$@"
|
||||
|
||||
@@ -21,7 +21,9 @@ if "%_JAVACMD%"=="" set _JAVACMD=java
|
||||
rem We use the value of the JAVA_OPTS environment variable if defined
|
||||
set _JAVA_OPTS=-Xmx256M -Xms32M -noverify
|
||||
|
||||
"%_JAVACMD%" %_JAVA_OPTS% -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar" org.jetbrains.jet.cli.js.K2JSCompiler %*
|
||||
"%_JAVACMD%" %_JAVA_OPTS% -cp "%_KOTLIN_HOME%\lib\kotlin-preloader.jar" ^
|
||||
org.jetbrains.jet.preloading.Preloader "${KOTLIN_HOME}/lib/kotlin-compiler.jar" ^
|
||||
org.jetbrains.jet.cli.jvm.K2JVMCompiler 4096 org.jetbrains.jet.cli.js.K2JSCompiler %*
|
||||
goto end
|
||||
|
||||
rem ##########################################################################
|
||||
|
||||
@@ -81,5 +81,5 @@ CPSELECT="-cp "
|
||||
"${JAVACMD:=java}" \
|
||||
$JAVA_OPTS \
|
||||
"${java_args[@]}" \
|
||||
${CPSELECT}"${KOTLIN_HOME}/lib/kotlin-compiler.jar" \
|
||||
org.jetbrains.jet.cli.jvm.K2JVMCompiler "$@"
|
||||
${CPSELECT}"${KOTLIN_HOME}/lib/kotlin-preloader.jar" \
|
||||
org.jetbrains.jet.preloading.Preloader "${KOTLIN_HOME}/lib/kotlin-compiler.jar" org.jetbrains.jet.cli.jvm.K2JVMCompiler 4096 "$@"
|
||||
|
||||
@@ -21,7 +21,9 @@ if "%_JAVACMD%"=="" set _JAVACMD=java
|
||||
rem We use the value of the JAVA_OPTS environment variable if defined
|
||||
set _JAVA_OPTS=-Xmx256M -Xms32M -noverify
|
||||
|
||||
"%_JAVACMD%" %_JAVA_OPTS% -cp "%_KOTLIN_HOME%\lib\kotlin-compiler.jar" org.jetbrains.jet.cli.jvm.K2JVMCompiler %*
|
||||
"%_JAVACMD%" %_JAVA_OPTS% -cp "%_KOTLIN_HOME%\lib\kotlin-preloader.jar" ^
|
||||
org.jetbrains.jet.preloading.Preloader "${KOTLIN_HOME}/lib/kotlin-compiler.jar" ^
|
||||
org.jetbrains.jet.cli.jvm.K2JVMCompiler 4096 org.jetbrains.jet.cli.jvm.K2JVMCompiler %*
|
||||
goto end
|
||||
|
||||
rem ##########################################################################
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
package org.jetbrains.jet.preloading;/*
|
||||
* Copyright 2010-2013 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.
|
||||
*/
|
||||
|
||||
import sun.misc.CompoundEnumeration;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class ClassPreloadingUtils {
|
||||
|
||||
/**
|
||||
* Creates a class loader that loads all classes from {@code jarFile} into memory to make loading faster (avoid skipping through zip archives).
|
||||
* @param jarFile a jar to load all classes from
|
||||
* @param classCountEstimation an estimated number of classes in a the jar
|
||||
* @param parent (nullable) parent class loader
|
||||
* @return a class loader that reads classes from memory
|
||||
* @throws IOException on from reading the jar
|
||||
*/
|
||||
public static ClassLoader preloadClasses(File jarFile, int classCountEstimation, ClassLoader parent) throws IOException {
|
||||
Map<String, byte[]> entries = loadAllClassesFromJar(jarFile, classCountEstimation);
|
||||
|
||||
return createMemoryBasedClassLoader(parent, jarFile, entries);
|
||||
}
|
||||
|
||||
private static ClassLoader createMemoryBasedClassLoader(
|
||||
final ClassLoader parent,
|
||||
final File jarFile,
|
||||
final Map<String, byte[]> preloadedResources
|
||||
) {
|
||||
return new ClassLoader(null) {
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
// Look in this class loader and then in the parent one
|
||||
Class<?> aClass = super.loadClass(name);
|
||||
if (aClass == null) {
|
||||
return parent.loadClass(name);
|
||||
}
|
||||
return aClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
String internalName = name.replace('.', '/').concat(".class");
|
||||
byte[] bytes = preloadedResources.get(internalName);
|
||||
if (bytes == null) return null;
|
||||
|
||||
return defineClass(name, bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected URL findResource(String name) {
|
||||
final byte[] bytes = preloadedResources.get(name);
|
||||
if (bytes == null) return null;
|
||||
|
||||
try {
|
||||
String path = "file:" + jarFile + "!" + name;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Enumeration<URL> findResources(String name) throws IOException {
|
||||
URL resource = findResource(name);
|
||||
if (resource == null) {
|
||||
return new CompoundEnumeration<URL>(new Enumeration[0]);
|
||||
}
|
||||
return Collections.enumeration(Collections.singletonList(resource));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Map<String, byte[]> loadAllClassesFromJar(File jarFile, int classNumberEstimate) throws IOException {
|
||||
Map<String, byte[]> classes = new HashMap<String, byte[]>(classNumberEstimate);
|
||||
|
||||
FileInputStream fileInputStream = new FileInputStream(jarFile);
|
||||
try {
|
||||
byte[] buffer = new byte[10 * 1024];
|
||||
ZipInputStream stream = new ZipInputStream(new BufferedInputStream(fileInputStream));
|
||||
while (true) {
|
||||
ZipEntry entry = stream.getNextEntry();
|
||||
if (entry == null) break;
|
||||
|
||||
ByteArrayOutputStreamWithPublicArray bytes = new ByteArrayOutputStreamWithPublicArray((int) entry.getSize());
|
||||
int count;
|
||||
while ((count = stream.read(buffer)) > 0) {
|
||||
bytes.write(buffer, 0, count);
|
||||
}
|
||||
if (!entry.isDirectory()) {
|
||||
classes.put(entry.getName(), bytes.getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
fileInputStream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static class ByteArrayOutputStreamWithPublicArray extends ByteArrayOutputStream {
|
||||
public ByteArrayOutputStreamWithPublicArray(int size) {
|
||||
super(size);
|
||||
}
|
||||
|
||||
// To avoid copying the array
|
||||
public byte[] getBytes() {
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.jetbrains.jet.preloading;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Preloader {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length < 3) {
|
||||
printUsageAndExit();
|
||||
}
|
||||
|
||||
File file = new File(args[0]);
|
||||
if (!file.exists()) {
|
||||
System.out.println("File does not exist: " + file);
|
||||
printUsageAndExit();
|
||||
}
|
||||
|
||||
String mainClassCanonicalName = args[1];
|
||||
|
||||
int classNumber;
|
||||
try {
|
||||
classNumber = Integer.parseInt(args[2]);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
System.out.println(e.getMessage());
|
||||
printUsageAndExit();
|
||||
return;
|
||||
}
|
||||
|
||||
ClassLoader parent = Preloader.class.getClassLoader();
|
||||
|
||||
ClassLoader preloaded = ClassPreloadingUtils.preloadClasses(file, classNumber, parent);
|
||||
|
||||
Class<?> mainClass = preloaded.loadClass(mainClassCanonicalName);
|
||||
Method mainMethod = mainClass.getMethod("main", String[].class);
|
||||
|
||||
mainMethod.invoke(0, new Object[] {Arrays.copyOfRange(args, 2, args.length)});
|
||||
}
|
||||
|
||||
private static void printUsageAndExit() {
|
||||
System.out.println("Usage: Preloader <path to jar> <main class> <class number estimate> <parameters to pass to the main class>");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user