diff options
Diffstat (limited to 'libjava/java/lang/VMCompiler.java')
-rw-r--r-- | libjava/java/lang/VMCompiler.java | 369 |
1 files changed, 0 insertions, 369 deletions
diff --git a/libjava/java/lang/VMCompiler.java b/libjava/java/lang/VMCompiler.java deleted file mode 100644 index 1f600f1..0000000 --- a/libjava/java/lang/VMCompiler.java +++ /dev/null @@ -1,369 +0,0 @@ -/* VMClassLoader.java -- Reference implementation of compiler interface - Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.lang; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStreamReader; -import java.security.MessageDigest; -import java.security.ProtectionDomain; -import java.security.NoSuchAlgorithmException; -import java.util.WeakHashMap; -import java.util.HashSet; -import java.util.Enumeration; -import java.util.StringTokenizer; -import java.util.Vector; -import gnu.gcj.runtime.SharedLibHelper; -import gnu.gcj.runtime.PersistentByteMap; -import gnu.java.security.hash.MD5; - -/** - * This class is just a per-VM reflection of java.lang.Compiler. - * All methods are defined identically. - */ -final class VMCompiler -{ - // True if we want to use gcj-jit. - public static boolean useCompiler = true; - - // True if we're able to use gcj-jit. - public static final boolean canUseCompiler; - - // Compiler to use. - public static String gcjJitCompiler; - - // Compiler options. - public static String gcjJitCompilerOptions; - - // Temporary directory to use. - public static String gcjJitTmpdir; - - public static boolean precompiles() - { - return (canUseCompiler & useCompiler); - } - - // This maps a ClassLoader to a set of SharedLibHelper objects that - // it has used. We do things this way to ensure that a - // SharedLibHelper is collected if and only if the ClassLoader is. - private static WeakHashMap sharedHelperMap = new WeakHashMap(); - - private static Vector precompiledMapFiles; - - // We create a single MD5 engine and then clone it whenever we want - // a new one. - - // We don't use - // - // md5Digest = MessageDigest.getInstance("MD5"); - // - // here because that loads a great deal of security provider code as - // interpreted bytecode -- before we're able to use this class to - // load precompiled classes. - - private static final MD5 md5Digest - = new gnu.java.security.hash.MD5(); - - static - { - gcjJitCompiler = System.getProperty("gnu.gcj.jit.compiler"); - if (gcjJitCompiler == null) - canUseCompiler = false; - else - { - gcjJitCompilerOptions = System.getProperty("gnu.gcj.jit.options", - "-g"); - gcjJitTmpdir = System.getProperty("gnu.gcj.jit.cachedir"); - // Note that we *don't* choose java.io.tmpdir as a default -- - // that would allow easy attacks against the VM. - if (gcjJitTmpdir == null) - canUseCompiler = false; - else - canUseCompiler = true; - } - - String prop = System.getProperty ("gnu.gcj.precompiled.db.path"); - if (prop != null) - { - precompiledMapFiles = new Vector(); - // Add the - StringTokenizer st - = new StringTokenizer (prop, - System.getProperty ("path.separator", ":")); - { - while (st.hasMoreElements ()) - { - String e = st.nextToken (); - try - { - PersistentByteMap map - = new PersistentByteMap - (e, PersistentByteMap.AccessMode.READ_ONLY); - precompiledMapFiles.add(map); - } - catch (IllegalArgumentException _) - { - // Not a map file - } - catch (java.io.IOException _) - { - } - catch (java.nio.BufferUnderflowException _) - { - // Invalid map file. - } - } - } - } - } - - /** - * Don't allow new `Compiler's to be made. - */ - private VMCompiler() - { - } - - private static Class loadSharedLibrary(ClassLoader loader, - String fileName, - ProtectionDomain domain, - String className) - { - Class c = null; - SharedLibHelper helper - = SharedLibHelper.findHelper (loader, fileName, domain.getCodeSource(), - domain, false); - c = helper.findClass (className); - if (c != null) - { - HashSet hs = (HashSet) sharedHelperMap.get(loader); - if (hs == null) - { - hs = new HashSet(); - sharedHelperMap.put(loader, hs); - } - hs.add(helper); - } - return c; - } - - /** - * Compile a class given the bytes for it. Returns the Class, or - * null if compilation failed or otherwise could not be done. - */ - public static Class compileClass(ClassLoader loader, - String name, byte[] data, - int offset, int len, - ProtectionDomain domain) - { - if (precompiledMapFiles == null && !precompiles()) - return null; - - byte digest[]; - - try - { - MD5 md = (MD5) md5Digest.clone(); - md.update(data); - digest = md.digest(); - } - catch (NullPointerException _) - { - // If md5Digest==null -- but really this should never happen - // either, since the MD5 digest is in libgcj. - return null; - } - - // We use lookaside cache files to determine whether these bytes - // correspond to a class file that is part of a precompiled DSO. - if (precompiledMapFiles != null) - { - try - { - Enumeration elements = precompiledMapFiles.elements(); - while (elements.hasMoreElements()) - { - PersistentByteMap map = (PersistentByteMap)elements.nextElement(); - byte[] soName = map.get(digest); - if (soName != null) - return loadSharedLibrary(loader, - new String(soName), - domain, name); - } - } - catch (Exception _) - { - } - catch (UnknownError _) - { - // SharedLibHelper will throw UnknownError if the dlopen - // fails for some reason. We ignore it and continue on. - } - } - - if (!precompiles()) - return null; - - try - { - // FIXME: Make sure that the class represented by the - // bytes in DATA really is the class named in NAME. Make - // sure it's not "java.*". - StringBuffer hexBytes = new StringBuffer(gcjJitTmpdir); - hexBytes.append(File.separatorChar); - int digestLength = digest.length; - for (int i = 0; i < digestLength; ++i) - { - int v = digest[i] & 0xff; - if (v < 16) - hexBytes.append('0'); - hexBytes.append(Integer.toHexString(v)); - } - - // FIXME: use System.mapLibraryName? - // I'm thinking we should use that, plus a class specified - // via a property that determines lookup policy. - File soFile = new File(hexBytes + ".so"); - if (soFile.isFile()) - return loadSharedLibrary (loader, soFile.toString(), domain, - name); - - File classFile = new File(hexBytes + ".class"); - classFile.delete(); - if (classFile.createNewFile() != true) - return null; - - FileOutputStream f = new FileOutputStream (classFile); - // FIXME: race condition if bytes change... ? - f.write(data, offset, len); - - // Invoke the compiler. - StringBuffer command = new StringBuffer(gcjJitCompiler); - command.append(" "); - command.append(classFile); - command.append(" "); - command.append(gcjJitCompilerOptions); - // These options are required. - command.append(" -findirect-dispatch -fjni -shared -fPIC -o "); - command.append(soFile); - Process p = Runtime.getRuntime().exec(command.toString()); - - // Read the process' stderr into a string. - StringBuffer err = new StringBuffer(); - InputStreamReader stderr = new InputStreamReader (p.getErrorStream()); - char[] inBuf = new char[500]; - int bytesRead; - while ((bytesRead = stderr.read (inBuf)) != -1) - err.append(inBuf, 0, bytesRead); - - if (p.waitFor() != 0) - { - // FIXME: we could log err.toString() somewhere... - return null; - } - - return loadSharedLibrary(loader, soFile.toString(), domain, name); - } - catch (Exception _) - { - return null; - } - } - - /** - * Compile the class named by <code>oneClass</code>. - * - * @param oneClass the class to compile - * @return <code>false</code> if no compiler is available or - * compilation failed, <code>true</code> if compilation succeeded - * @throws NullPointerException if oneClass is null - */ - public static boolean compileClass(Class oneClass) - { - // Never succeed. - return false; - } - - /** - * Compile the classes whose name matches <code>classNames</code>. - * - * @param classNames the name of classes to compile - * @return <code>false</code> if no compiler is available or - * compilation failed, <code>true</code> if compilation succeeded - * @throws NullPointerException if classNames is null - */ - public static boolean compileClasses(String classNames) - { - // Note the incredibly lame interface. Always fail. - return false; - } - - /** - * This method examines the argument and performs an operation - * according to the compilers documentation. No specific operation - * is required. - * - * @param arg a compiler-specific argument - * @return a compiler-specific value, including null - * @throws NullPointerException if the compiler doesn't like a null arg - */ - public static Object command(Object arg) - { - // Our implementation defines this to a no-op. - return null; - } - - /** - * Calling <code>Compiler.enable()</code> will cause the compiler - * to resume operation if it was previously disabled; provided that a - * compiler even exists. - */ - public static void enable() - { - useCompiler = true; - } - - /** - * Calling <code>Compiler.disable()</code> will cause the compiler - * to be suspended; provided that a compiler even exists. - */ - public static void disable() - { - useCompiler = false; - } -} |