Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
* Copyright (c) 2009, 2019 Mountainminds GmbH & Co. KG and Contributors
* 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:
* Evgeny Mandrikov - initial API and implementation
*
*******************************************************************************/
package org.jacoco.core.runtime;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* {@link IRuntime} which defines a new class using
* {@code java.lang.invoke.MethodHandles.Lookup.defineClass} introduced in Java
* 9. Module where class will be defined must be opened to at least module of
* this class.
*/
public class InjectedClassRuntime extends AbstractRuntime {
private static final String FIELD_NAME = "data";
private static final String FIELD_TYPE = "Ljava/lang/Object;";
private final Class locator;
private final String injectedClassName;
/**
* Creates a new runtime which will define a class to the same class loader
* and in the same package and protection domain as given class.
*
* @param locator
* class to identify the target class loader and package
* @param simpleClassName
* simple name of the class to be defined
*/
public InjectedClassRuntime(final Class locator,
final String simpleClassName) {
this.locator = locator;
this.injectedClassName = locator.getPackage().getName().replace('.',
'/') + '/' + simpleClassName;
}
@Override
public void startup(final RuntimeData data) throws Exception {
super.startup(data);
Lookup //
.privateLookupIn(locator, Lookup.lookup()) //
.defineClass(createClass(injectedClassName)) //
.getField(FIELD_NAME) //
.set(null, data);
}
public void shutdown() {
// nothing to do
}
public int generateDataAccessor(final long classid, final String classname,
final int probecount, final MethodVisitor mv) {
mv.visitFieldInsn(Opcodes.GETSTATIC, injectedClassName, FIELD_NAME,
FIELD_TYPE);
RuntimeData.generateAccessCall(classid, classname, probecount, mv);
return 6;
}
private static byte[] createClass(final String name) {
final ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V9, Opcodes.ACC_SYNTHETIC | Opcodes.ACC_PUBLIC,
name.replace('.', '/'), null, "java/lang/Object", null);
cw.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, FIELD_NAME,
FIELD_TYPE, null, null);
cw.visitEnd();
return cw.toByteArray();
}
/**
* Provides access to classes {@code java.lang.invoke.MethodHandles} and
* {@code java.lang.invoke.MethodHandles.Lookup} introduced in Java 8.
*/
private static class Lookup {
private final Object instance;
private Lookup(final Object instance) {
this.instance = instance;
}
/**
* @return a lookup object for the caller of this method
*/
static Lookup lookup() throws Exception {
return new Lookup(Class //
.forName("java.lang.invoke.MethodHandles") //
.getMethod("lookup") //
.invoke(null));
}
/**
* See corresponding method introduced in Java 9.
*
* @param targetClass
* the target class
* @param lookup
* the caller lookup object
* @return a lookup object for the target class, with private access
*/
static Lookup privateLookupIn(final Class targetClass,
final Lookup lookup) throws Exception {
return new Lookup(Class //
.forName("java.lang.invoke.MethodHandles") //
.getMethod("privateLookupIn", Class.class,
Class.forName(
"java.lang.invoke.MethodHandles$Lookup")) //
.invoke(null, targetClass, lookup.instance));
}
/**
* See corresponding method introduced in Java 9.
*
* @param bytes
* the class bytes
* @return class
*/
Class defineClass(final byte[] bytes) throws Exception {
return (Class) Class //
.forName("java.lang.invoke.MethodHandles$Lookup")
.getMethod("defineClass", byte[].class)
.invoke(this.instance, new Object[] { bytes });
}
}
}