All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dorkbox.jna.JnaClassUtils Maven / Gradle / Ivy

/*
 * Copyright 2016 dorkbox, llc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dorkbox.jna;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import com.sun.jna.JNIEnv;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.win32.StdCallFunctionMapper;

import dorkbox.os.OS;

// http://hg.openjdk.java.net/jdk/jdk10/file/b09e56145e11/src/java.base/share/native/libjava/ClassLoader.c
// http://hg.openjdk.java.net/jdk10/jdk10/jdk/file/777356696811/src/java.base/share/native/libjava/ClassLoader.c
// http://hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/java.base/share/native/libjava/ClassLoader.c
// http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/be698ac28848/src/share/native/java/lang/ClassLoader.c
// http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/tip/src/share/vm/prims/jvm.cpp

// objdump -T  | grep foo
// otool -T  | grep foo

/**
 * Gives us the ability to inject bytes into the "normal" classloader, or directly into java's bootstrap classloader.
 * 

* When injecting into the bootstrap classloader, this COMPLETELY bypass all security checks, as it calls native methods directly via JNA. */ @SuppressWarnings({"WeakerAccess", "unchecked"}) public class JnaClassUtils { private static final JVM libJvm; // Note: this does not work in java8 x86 *on windows XP windows7, etc. It only works on x64 @SuppressWarnings("UnusedReturnValue") public interface JVM extends com.sun.jna.Library { void JVM_DefineClass(JNIEnv env, String name, Object classLoader, byte[] buffer, int length, Object protectionDomain); // Class JVM_FindLoadedClass(JNIEnv env, Object classLoader, JString name); } private static final String libName; static { if (OS.isMacOsX()) { if (OS.javaVersion < 7) { libName = "JavaVM"; } else { String javaLocation = System.getProperty("java.home"); // have to explicitly specify the JVM library via full path // this is OK, because for java on MacOSX, this is the only location it can exist libName = javaLocation + "/lib/server/libjvm.dylib"; } } else { libName = "jvm"; } // function name is SLIGHTLY different on windows x32 java builds. // For actual name use: http://www.nirsoft.net/utils/dll_export_viewer.html //noinspection rawtypes Map options = new HashMap(); options.put(Library.OPTION_ALLOW_OBJECTS, Boolean.TRUE); if (OS.isWindows() && OS.is32bit()) { options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper() { @Override public String getFunctionName(NativeLibrary library, Method method) { String methodName = method.getName(); if (methodName.equals("JVM_DefineClass")) { // specifically Oracle Java 32bit builds. Tested on XP and Win7 return "_JVM_DefineClass@24"; } return methodName; } }); libJvm = Native.load(libName, JVM.class, options); } else { libJvm = Native.load(libName, JVM.class, options); } } /** * Defines a class in the current threads class-loader * * @param classBytes the bytes of the class to define */ public static void defineClass(final byte[] classBytes) throws Exception { java.lang.ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); defineClass(classLoader, classBytes); } /** * Inject class bytes directly into the bootstrap classloader. *

* This is a VERY DANGEROUS method to use! * * @param classLoader the classLoader to use. null will use the BOOTSTRAP classloader * @param classBytes the bytes to inject */ @SuppressWarnings("RedundantThrows") public static void defineClass(java.lang.ClassLoader classLoader, byte[] classBytes) throws Exception { // inject into the FIRST JVM that are started by us (is USUALLY 1, but not always) libJvm.JVM_DefineClass(JNIEnv.CURRENT, null, classLoader, classBytes, classBytes.length, null); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy