/* * 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()); } } }