/*
* Copyright (C) 2015, 2016 higherfrequencytrading.com
* Copyright (C) 2016 Roman Leventov
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.openhft.chronicle.values;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* This class support loading and debugging Java Classes dynamically.
*/
enum CompilerUtils {
;
public static final CachedCompiler CACHED_COMPILER = new CachedCompiler();
private static final Method DEFINE_CLASS_METHOD;
static JavaCompiler s_compiler;
static StandardJavaFileManager s_standardJavaFileManager;
static {
try {
DEFINE_CLASS_METHOD = ClassLoader.class.getDeclaredMethod(
"defineClass", String.class, byte[].class, int.class, int.class);
DEFINE_CLASS_METHOD.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
}
}
static {
reset();
}
private static void reset() {
s_compiler = ToolProvider.getSystemJavaCompiler();
if (s_compiler == null) {
try {
Class<?> javacTool = Class.forName("com.sun.tools.javac.api.JavacTool");
Method create = javacTool.getMethod("create");
s_compiler = (JavaCompiler) create.invoke(null);
} catch (Exception e) {
throw new AssertionError(e);
}
}
s_standardJavaFileManager = s_compiler.getStandardFileManager(null, null, null);
}
/**
* Define a class for byte code.
*
* @param classLoader to load the class into.
* @param className expected to load.
* @param bytes of the byte code.
*/
public static Class defineClass(
@Nullable ClassLoader classLoader, @NotNull String className, @NotNull byte[] bytes) {
try {
return (Class) DEFINE_CLASS_METHOD
.invoke(classLoader, className, bytes, 0, bytes.length);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
} catch (InvocationTargetException e) {
//noinspection ThrowInsideCatchBlockWhichIgnoresCaughtException
throw new AssertionError(e.getCause());
}
}
}