/** * Copyright (c) 2014 - 2017 Frank Appel * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Frank Appel - initial API and implementation */ package com.codeaffine.eclipse.swt.util; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.ProtectionDomain; public class Unsafe { private Object unsafeInstance; private Method allocateInstance; private Method defineClass; public Unsafe() { try { unsafeInstance = getUnsafeInstance(); allocateInstance = getAllocateInstanceMethod(); defineClass = getDefineClassMethod(); } catch( Exception unresolvable ) { throw new IllegalStateException( unresolvable ); } } public <T> T newInstance( Class<T> type ) { try { return type.cast( allocateInstance.invoke( unsafeInstance, type ) ); } catch( IllegalAccessException iae ) { throw new RuntimeException( iae ); } catch( InvocationTargetException ite ) { throw toRuntimeException( ite ); } } public Class<?> defineClass( String name, byte[] bytes, int offset, int length, ClassLoader loader, ProtectionDomain domain ) { Class<?> result = loadFromClassLoader( name, loader ); if( result == null ) { result = defineClassUnsafe( name, bytes, offset, length, loader, domain ); } return result; } private static Object getUnsafeInstance() throws Exception { Field unsafeField = getUnsafeClass().getDeclaredField( "theUnsafe" ); unsafeField.setAccessible( true ); return unsafeField.get( null ); } private static Method getAllocateInstanceMethod() throws Exception { return getUnsafeClass().getMethod( "allocateInstance", Class.class ); } private static Method getDefineClassMethod() throws Exception { return getUnsafeClass().getMethod( "defineClass", String.class, byte[].class, int.class, int.class, ClassLoader.class, ProtectionDomain.class ); } private static Class<?> getUnsafeClass() throws ClassNotFoundException { return Unsafe.class.getClassLoader().loadClass( "sun.misc.Unsafe" ); } private static Class<?> loadFromClassLoader( String name, ClassLoader loader ) { try { return loader.loadClass( name ); } catch( SecurityException ignored ) { return null; } catch( ClassNotFoundException ignored ) { return null; } } private Class<?> defineClassUnsafe( String name, byte[] bytes, int offset, int length, ClassLoader loader, ProtectionDomain domain ) { try { return ( Class<?> )defineClass.invoke( unsafeInstance, name, bytes, Integer.valueOf( offset), Integer.valueOf( length ), loader, domain ); } catch( RuntimeException rte ) { throw rte; } catch( InvocationTargetException ite ) { throw toRuntimeException( ite ); } catch( IllegalAccessException iae ) { throw new RuntimeException( iae ); } } private static RuntimeException toRuntimeException( InvocationTargetException e ) { if( e.getCause() instanceof RuntimeException ) { return ( RuntimeException )e.getCause(); } return new RuntimeException( e.getCause() ); } }