hotspot/test/testlibrary/com/oracle/java/testlibrary/InMemoryJavaCompiler.java
author ehelin
Wed, 07 Aug 2013 16:47:32 +0200
changeset 19322 e35f9ed4f081
permissions -rw-r--r--
8014659: NPG: performance counters for compressed klass space Reviewed-by: mgerdin, coleenp, hseigel, jmasa, ctornqvi
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
19322
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     1
/*
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     2
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     4
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     7
 * published by the Free Software Foundation.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     8
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    13
 * accompanied this code).
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    14
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    18
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    21
 * questions.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    22
 */
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    23
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    24
package com.oracle.java.testlibrary;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    25
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    26
import java.io.ByteArrayOutputStream;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    27
import java.io.IOException;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    28
import java.io.OutputStream;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    29
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    30
import java.net.URI;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    31
import java.util.Arrays;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    32
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    33
import javax.tools.ForwardingJavaFileManager;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    34
import javax.tools.ForwardingJavaFileManager;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    35
import javax.tools.FileObject;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    36
import javax.tools.JavaCompiler;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    37
import javax.tools.JavaCompiler.CompilationTask;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    38
import javax.tools.JavaFileManager;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    39
import javax.tools.JavaFileObject;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    40
import javax.tools.JavaFileObject.Kind;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    41
import javax.tools.SimpleJavaFileObject;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    42
import javax.tools.ToolProvider;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    43
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    44
/**
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    45
 * {@code InMemoryJavaCompiler} can be used for compiling a {@link
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    46
 * CharSequence} to a {@code byte[]}.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    47
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    48
 * The compiler will not use the file system at all, instead using a {@link
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    49
 * ByteArrayOutputStream} for storing the byte code. For the source code, any
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    50
 * kind of {@link CharSequence} can be used, e.g. {@link String}, {@link
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    51
 * StringBuffer} or {@link StringBuilder}.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    52
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    53
 * The {@code InMemoryCompiler} can easily be used together with a {@code
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    54
 * ByteClassLoader} to easily compile and load source code in a {@link String}:
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    55
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    56
 * <pre>
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    57
 * {@code
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    58
 * import com.oracle.java.testlibrary.InMemoryJavaCompiler;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    59
 * import com.oracle.java.testlibrary.ByteClassLoader;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    60
 *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    61
 * class Example {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    62
 *     public static void main(String[] args) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    63
 *         String className = "Foo";
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    64
 *         String sourceCode = "public class " + className + " {" +
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    65
 *                             "    public void bar() {" +
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    66
 *                             "        System.out.println("Hello from bar!");" +
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    67
 *                             "    }" +
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    68
 *                             "}";
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    69
 *         byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode);
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    70
 *         Class fooClass = ByteClassLoader.load(className, byteCode);
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    71
 *     }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    72
 * }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    73
 * }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    74
 * </pre>
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    75
 */
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    76
public class InMemoryJavaCompiler {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    77
    private static class MemoryJavaFileObject extends SimpleJavaFileObject {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    78
        private final String className;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    79
        private final CharSequence sourceCode;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    80
        private final ByteArrayOutputStream byteCode;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    81
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    82
        public MemoryJavaFileObject(String className, CharSequence sourceCode) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    83
            super(URI.create("string:///" + className.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE);
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    84
            this.className = className;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    85
            this.sourceCode = sourceCode;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    86
            this.byteCode = new ByteArrayOutputStream();
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    87
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    88
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    89
        @Override
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    90
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    91
            return sourceCode;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    92
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    93
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    94
        @Override
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    95
        public OutputStream openOutputStream() throws IOException {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    96
            return byteCode;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    97
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    98
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
    99
        public byte[] getByteCode() {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   100
            return byteCode.toByteArray();
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   101
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   102
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   103
        public String getClassName() {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   104
            return className;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   105
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   106
    }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   107
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   108
    private static class FileManagerWrapper extends ForwardingJavaFileManager {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   109
        private MemoryJavaFileObject file;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   110
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   111
        public FileManagerWrapper(MemoryJavaFileObject file) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   112
            super(getCompiler().getStandardFileManager(null, null, null));
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   113
            this.file = file;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   114
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   115
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   116
        @Override
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   117
        public JavaFileObject getJavaFileForOutput(Location location, String className,
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   118
                                                   Kind kind, FileObject sibling)
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   119
            throws IOException {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   120
            if (!file.getClassName().equals(className)) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   121
                throw new IOException("Expected class with name " + file.getClassName() +
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   122
                                      ", but got " + className);
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   123
            }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   124
            return file;
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   125
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   126
    }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   127
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   128
    /**
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   129
     * Compiles the class with the given name and source code.
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   130
     *
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   131
     * @param className The name of the class
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   132
     * @param sourceCode The source code for the class with name {@code className}
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   133
     * @throws RuntimeException if the compilation did not succeed
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   134
     * @return The resulting byte code from the compilation
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   135
     */
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   136
    public static byte[] compile(String className, CharSequence sourceCode) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   137
        MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode);
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   138
        CompilationTask task = getCompilationTask(file);
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   139
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   140
        if(!task.call()) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   141
            throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode);
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   142
        }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   143
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   144
        return file.getByteCode();
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   145
    }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   146
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   147
    private static JavaCompiler getCompiler() {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   148
        return ToolProvider.getSystemJavaCompiler();
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   149
    }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   150
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   151
    private static CompilationTask getCompilationTask(MemoryJavaFileObject file) {
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   152
        return getCompiler().getTask(null, new FileManagerWrapper(file), null, null, null, Arrays.asList(file));
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   153
    }
e35f9ed4f081 8014659: NPG: performance counters for compressed klass space
ehelin
parents:
diff changeset
   154
}