首先看jacoco premain 入口:
/*******************************************************************************
* Copyright (c) 2009, 2018 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:
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
package org.jacoco.agent.rt.internal;
import java.lang.instrument.Instrumentation;
import org.jacoco.core.runtime.AgentOptions;
import org.jacoco.core.runtime.IRuntime;
import org.jacoco.core.runtime.ModifiedSystemClassRuntime;
/**
* The agent which is referred as the <code>Premain-Class</code>. The agent
* configuration is provided with the agent parameters in the command line.
*/
public final class PreMain {
private PreMain() {
// no instances
}
/**
* This method is called by the JVM to initialize Java agents.
*
* @param options
* agent options
* @param inst
* instrumentation callback provided by the JVM
* @throws Exception
* in case initialization fails
*/
public static void premain(final String options, final Instrumentation inst)
throws Exception {
final AgentOptions agentOptions = new AgentOptions(options);
final Agent agent = Agent.getInstance(agentOptions);
final IRuntime runtime = createRuntime(inst);
runtime.startup(agent.getData());
inst.addTransformer(new CoverageTransformer(runtime, agentOptions,
IExceptionLogger.SYSTEM_ERR));
}
private static IRuntime createRuntime(final Instrumentation inst)
throws Exception {
return ModifiedSystemClassRuntime.createFor(inst, "java/lang/UnknownError");
}
}
入口函数premain: 参数 Instrumentation类是java.lang 下面的类
public static void premain(final String options, final Instrumentation inst)
throws Exception {
final AgentOptions agentOptions = new AgentOptions(options);
final Agent agent = Agent.getInstance(agentOptions);
final IRuntime runtime = createRuntime(inst);
runtime.startup(agent.getData());
inst.addTransformer(new CoverageTransformer(runtime, agentOptions,
IExceptionLogger.SYSTEM_ERR));
}
然后调用了CoverageTransformer 类,这个类和 premain同一个包下面:
看下 CoverageTransformer 类:
/*******************************************************************************
* Copyright (c) 2009, 2018 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:
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
package org.jacoco.agent.rt.internal;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import org.jacoco.core.instr.Instrumenter;
import org.jacoco.core.runtime.AgentOptions;
import org.jacoco.core.runtime.IRuntime;
import org.jacoco.core.runtime.WildcardMatcher;
/**
* Class file transformer to instrument classes for code coverage analysis.
*/
public class CoverageTransformer implements ClassFileTransformer {
private static final String AGENT_PREFIX;
static {
final String name = CoverageTransformer.class.getName();
AGENT_PREFIX = toVMName(name.substring(0, name.lastIndexOf('.')));
}
private final Instrumenter instrumenter;
private final IExceptionLogger logger;
private final WildcardMatcher includes;
private final WildcardMatcher excludes;
private final WildcardMatcher exclClassloader;
private final ClassFileDumper classFileDumper;
private final boolean inclBootstrapClasses;
private final boolean inclNoLocationClasses;
/**
* New transformer with the given delegates.
*
* @param runtime
* coverage runtime
* @param options
* configuration options for the generator
* @param logger
* logger for exceptions during instrumentation
*/
public CoverageTransformer(final IRuntime runtime,
final AgentOptions options, final IExceptionLogger logger) {
this.instrumenter = new Instrumenter(runtime);
this.logger = logger;
// Class names will be reported in VM notation:
includes = new WildcardMatcher(toVMName(options.getIncludes()));
excludes = new WildcardMatcher(toVMName(options.getExcludes()));
exclClassloader = new WildcardMatcher(options.getExclClassloader());
classFileDumper = new ClassFileDumper(options.getClassDumpDir());
inclBootstrapClasses = options.getInclBootstrapClasses();
inclNoLocationClasses = options.getInclNoLocationClasses();
}
public byte[] transform(final ClassLoader loader, final String classname,
final Class<?> classBeingRedefined,
final ProtectionDomain protectionDomain,
final byte[] classfileBuffer) throws IllegalClassFormatException {
// We do not support class retransformation:
if (classBeingRedefined != null) {
return null;
}
if (!filter(loader, classname, protectionDomain)) {
return null;
}
try {
classFileDumper.dump(classname, classfileBuffer);
return instrumenter.instrument(classfileBuffer, classname);
} catch (final Exception ex) {
final IllegalClassFormatException wrapper = new IllegalClassFormatException(
ex.getMessage());
wrapper.initCause(ex);
// Report this, as the exception is ignored by the JVM:
logger.logExeption(wrapper);
throw wrapper;
}
}
/**
* Checks whether this class should be instrumented.
*
* @param loader
* loader for the class
* @param classname
* VM name of the class to check
* @param protectionDomain
* protection domain for the class
* @return <code>true</code> if the class should be instrumented
*/
boolean filter(final ClassLoader loader, final String classname,
final ProtectionDomain protectionDomain) {
if (loader == null) {
if (!inclBootstrapClasses) {
return false;
}
} else {
if (!inclNoLocationClasses && !hasSourceLocation(protectionDomain)) {
return false;
}
if (exclClassloader.matches(loader.getClass().getName())) {
return false;
}
}
return !classname.startsWith(AGENT_PREFIX) &&
includes.matches(classname) &&
!excludes.matches(classname);
}
/**
* Checks whether this protection domain is associated with a source
* location.
*
* @param protectionDomain
* protection domain to check (or <code>null</code>)
* @return <code>true</code> if a source location is defined
*/
private boolean hasSourceLocation(final ProtectionDomain protectionDomain) {
if (protectionDomain == null) {
return false;
}
final CodeSource codeSource = protectionDomain.getCodeSource();
if (codeSource == null) {
return false;
}
return codeSource.getLocation() != null;
}
private static String toVMName(final String srcName) {
return srcName.replace('.', '/');
}
}
这个类中关键方法:
public byte[] transform(final ClassLoader loader, final String classname,
final Class<?> classBeingRedefined,
final ProtectionDomain protectionDomain,
final byte[] classfileBuffer) throws IllegalClassFormatException {
// We do not support class retransformation:
if (classBeingRedefined != null) {
return null;
}
if (!filter(loader, classname, protectionDomain)) {
return null;
}
try {
classFileDumper.dump(classname, classfileBuffer);
return instrumenter.instrument(classfileBuffer, classname);
} catch (final Exception ex) {
final IllegalClassFormatException wrapper = new IllegalClassFormatException(
ex.getMessage());
wrapper.initCause(ex);
// Report this, as the exception is ignored by the JVM:
logger.logExeption(wrapper);
throw wrapper;
}
}
调用了classFileDumper 类:
/*******************************************************************************
* Copyright (c) 2009, 2018 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:
* Marc R. Hoffmann - initial API and implementation
*
*******************************************************************************/
package org.jacoco.agent.rt.internal;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.jacoco.core.internal.data.CRC64;
/**
* Internal dumper for class files.
*/
class ClassFileDumper {
private final File location;
/**
* Create a new dumper for the given location.
*
* @param location
* relative path to dump directory. <code>null</code> if no dumps
* should be written
*/
ClassFileDumper(final String location) {
if (location == null) {
this.location = null;
} else {
this.location = new File(location);
}
}
/**
* Dumps the given binary content under the given name if a non-
* <code>null</code> location has been specified.
*
* @param name
* qualified class name in VM notation
* @param contents
* binary contents
* @throws IOException
* in case of problems while dumping the file
*/
void dump(final String name, final byte[] contents) throws IOException {
if (location != null) {
final File outputdir;
final String localname;
final int pkgpos = name.lastIndexOf('/');
if (pkgpos != -1) {
outputdir = new File(location, name.substring(0, pkgpos));
localname = name.substring(pkgpos + 1);
} else {
outputdir = location;
localname = name;
}
outputdir.mkdirs();
final Long id = Long.valueOf(CRC64.classId(contents));
final File file = new File(outputdir, String.format(
"%s.%016x.class", localname, id));
final OutputStream out = new FileOutputStream(file);
out.write(contents);
out.close();
}
}
}
这个类将class out 输出,上面transform方法在调用的时候同时使用:
classFileDumper.dump(classname, classfileBuffer);
return instrumenter.instrument(classfileBuffer, classname);
final class InstrSupport类:
public static final String DATAFIELD_DESC = "[Z";
// === Init Method ===
/**
* Name of the initialization method.
*/
public static final String INITMETHOD_NAME = "$jacocoInit";
/**
* Descriptor of the initialization method.
*/
public static final String INITMETHOD_DESC = "()[Z";
public static void assertNotInstrumented(final String member,
final String owner) throws IllegalStateException {
if (member.equals(DATAFIELD_NAME) || member.equals(INITMETHOD_NAME)) {
throw new IllegalStateException(format(
"Class %s is already instrumented.", owner));
}
}
这个类是final 主要作为单例的使用,ClassInstrumenter, ClassAnalyzer调用InstrSupport
ClassAnalyzer 类调用如下:
@Override
public MethodProbesVisitor visitMethod(final int access, final String name,
final String desc, final String signature, final String[] exceptions) {
InstrSupport.assertNotInstrumented(name, coverage.getName());
return new MethodAnalyzer(coverage.getName(), coverage.getSuperName(),
stringPool.get(name), stringPool.get(desc),
stringPool.get(signature), probes, Filters.ALL) {
@Override
public void visitEnd() {
super.visitEnd();
final IMethodCoverage methodCoverage = getCoverage();
if (methodCoverage.getInstructionCounter().getTotalCount() > 0) {
// Only consider methods that actually contain code
coverage.addMethod(methodCoverage);
}
}
};
}
@Override
public FieldVisitor visitField(final int access, final String name,
final String desc, final String signature, final Object value) {
InstrSupport.assertNotInstrumented(name, coverage.getName());
return super.visitField(access, name, desc, signature, value);
}
public class ClassInstrumenter extends ClassProbesVisitor 类;ClassInstrumenter类的调用:
@Override
public FieldVisitor visitField(final int access, final String name,
final String desc, final String signature, final Object value) {
InstrSupport.assertNotInstrumented(name, className);
return super.visitField(access, name, desc, signature, value);
}
@Override
public MethodProbesVisitor visitMethod(final int access, final String name,
final String desc, final String signature, final String[] exceptions) {
InstrSupport.assertNotInstrumented(name, className);
final MethodVisitor mv = cv.visitMethod(access, name, desc, signature,
exceptions);
if (mv == null) {
return null;
}
final MethodVisitor frameEliminator = new DuplicateFrameEliminator(mv);
final ProbeInserter probeVariableInserter = new ProbeInserter(access,
name, desc, frameEliminator, probeArrayStrategy);
return new MethodInstrumenter(probeVariableInserter,
probeVariableInserter);
}
********** Instrumenter类如下:
public byte[] instrument(final ClassReader reader) {
final ClassWriter writer = new ClassWriter(reader, 0) {
@Override
protected String getCommonSuperClass(final String type1,
final String type2) {
throw new IllegalStateException();
}
};
final IProbeArrayStrategy strategy = ProbeArrayStrategyFactory
.createFor(reader, accessorGenerator);
final ClassVisitor visitor = new ClassProbesAdapter(
new ClassInstrumenter(strategy, writer), true);
reader.accept(visitor, ClassReader.EXPAND_FRAMES);
return writer.toByteArray();
}
public byte[] instrument(final byte[] buffer, final String name)
throws IOException {
try {
return instrument(new ClassReader(buffer));
} catch (final RuntimeException e) {
throw instrumentError(name, e);
}
}
public byte[] instrument(final InputStream input, final String name)
throws IOException {
final byte[] bytes;
try {
bytes = InputStreams.readFully(input);
} catch (final IOException e) {
throw instrumentError(name, e);
}
return instrument(bytes, name);
}
public void instrument(final InputStream input, final OutputStream output,
final String name) throws IOException {
output.write(instrument(input, name));
}
private IOException instrumentError(final String name,
final Exception cause) {
final IOException ex = new IOException(
String.format("Error while instrumenting %s.", name));
ex.initCause(cause);
return ex;
}
从这个类的代码看,instrument(input,output,string)调用instrument(input,string),后者再调用instrument([],string),再调用instrument(classreader)
所以最终的出口在于最下面的instrument(input,output,string),下面是剩余部分代码:
public int instrumentAll(final InputStream input, final OutputStream output,
final String name) throws IOException {
final ContentTypeDetector detector;
try {
detector = new ContentTypeDetector(input);
} catch (final IOException e) {
throw instrumentError(name, e);
}
switch (detector.getType()) {
case ContentTypeDetector.CLASSFILE:
instrument(detector.getInputStream(), output, name);
return 1;
case ContentTypeDetector.ZIPFILE:
return instrumentZip(detector.getInputStream(), output, name);
case ContentTypeDetector.GZFILE:
return instrumentGzip(detector.getInputStream(), output, name);
case ContentTypeDetector.PACK200FILE:
return instrumentPack200(detector.getInputStream(), output, name);
default:
copy(detector.getInputStream(), output, name);
return 0;
}
}
private int instrumentZip(final InputStream input,
final OutputStream output, final String name) throws IOException {
final ZipInputStream zipin = new ZipInputStream(input);
final ZipOutputStream zipout = new ZipOutputStream(output);
ZipEntry entry;
int count = 0;
while ((entry = nextEntry(zipin, name)) != null) {
final String entryName = entry.getName();
if (signatureRemover.removeEntry(entryName)) {
continue;
}
zipout.putNextEntry(new ZipEntry(entryName));
if (!signatureRemover.filterEntry(entryName, zipin, zipout)) {
count += instrumentAll(zipin, zipout, name + "@" + entryName);
}
zipout.closeEntry();
}
zipout.finish();
return count;
}
private ZipEntry nextEntry(final ZipInputStream input,
final String location) throws IOException {
try {
return input.getNextEntry();
} catch (final IOException e) {
throw instrumentError(location, e);
}
}
private int instrumentGzip(final InputStream input,
final OutputStream output, final String name) throws IOException {
final GZIPInputStream gzipInputStream;
try {
gzipInputStream = new GZIPInputStream(input);
} catch (final IOException e) {
throw instrumentError(name, e);
}
final GZIPOutputStream gzout = new GZIPOutputStream(output);
final int count = instrumentAll(gzipInputStream, gzout, name);
gzout.finish();
return count;
}
private int instrumentPack200(final InputStream input,
final OutputStream output, final String name) throws IOException {
final InputStream unpackedInput;
try {
unpackedInput = Pack200Streams.unpack(input);
} catch (final IOException e) {
throw instrumentError(name, e);
}
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
final int count = instrumentAll(unpackedInput, buffer, name);
Pack200Streams.pack(buffer.toByteArray(), output);
return count;
}
private void copy(final InputStream input, final OutputStream output,
final String name) throws IOException {
final byte[] buffer = new byte[1024];
int len;
while ((len = read(input, buffer, name)) != -1) {
output.write(buffer, 0, len);
}
}
private int read(final InputStream input, final byte[] buffer,
final String name) throws IOException {
try {
return input.read(buffer);
} catch (final IOException e) {
throw instrumentError(name, e);
}
}
核心关键是instrumentAll这个方法,这个方法根据文件包是class还是zip,或者gz等,不同的加载方式。
jacoco loadclass入口类:CoverageTransformer
public class CoverageTransformer
implements ClassFileTransformer
{
private static final String AGENT_PREFIX;
private final Instrumenter instrumenter;
private final IExceptionLogger logger;
private final WildcardMatcher includes;
private final WildcardMatcher excludes;
private final WildcardMatcher exclClassloader;
private final ClassFileDumper classFileDumper;
private final boolean inclBootstrapClasses;
private final boolean inclNoLocationClasses;
static
{
String name = CoverageTransformer.class.getName();
AGENT_PREFIX = toVMName(name.substring(0, name.lastIndexOf('.')));
}
public CoverageTransformer(IRuntime runtime, AgentOptions options, IExceptionLogger logger)
{
this.instrumenter = new Instrumenter(runtime);
this.logger = logger;
this.includes = new WildcardMatcher(toVMName(options.getIncludes()));
this.excludes = new WildcardMatcher(toVMName(options.getExcludes()));
this.exclClassloader = new WildcardMatcher(options.getExclClassloader());
this.classFileDumper = new ClassFileDumper(options.getClassDumpDir());
this.inclBootstrapClasses = options.getInclBootstrapClasses();
this.inclNoLocationClasses = options.getInclNoLocationClasses();
}
public byte[] transform(ClassLoader loader, String classname, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer)
throws IllegalClassFormatException
{
if (classBeingRedefined != null) {
return null;
}
if (!filter(loader, classname, protectionDomain)) {
return null;
}
try
{
this.classFileDumper.dump(classname, classfileBuffer);
return this.instrumenter.instrument(classfileBuffer, classname);
}
catch (Exception ex)
{
IllegalClassFormatException wrapper = new IllegalClassFormatException(ex.getMessage());
wrapper.initCause(ex);
this.logger.logExeption(wrapper);
throw wrapper;
}
}
boolean filter(ClassLoader loader, String classname, ProtectionDomain protectionDomain)
{
if (loader == null)
{
if (!this.inclBootstrapClasses) {
return false;
}
}
else
{
if ((!this.inclNoLocationClasses) && (!hasSourceLocation(protectionDomain))) {
return false;
}
if (this.exclClassloader.matches(loader.getClass().getName())) {
return false;
}
}
return (!classname.startsWith(AGENT_PREFIX)) && (this.includes.matches(classname)) && (!this.excludes.matches(classname));
}
private boolean hasSourceLocation(ProtectionDomain protectionDomain)
{
if (protectionDomain == null) {
return false;
}
CodeSource codeSource = protectionDomain.getCodeSource();
if (codeSource == null) {
return false;
}
return codeSource.getLocation() != null;
}
private static String toVMName(String srcName)
{
return srcName.replace('.', '/');
}
}
核心的两条代码:transform
try{
this.classFileDumper.dump(classname, classfileBuffer);
return this.instrumenter.instrument(classfileBuffer, classname);
}
********** 具体报错日志的分析:
java.lang.instrument.IllegalClassFormatException: Error while instrumenting class com/suning/srcdas/address/business/AddressBusiness.
at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:93)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:401)
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1432)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1377)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:641)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:609)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1484)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:425)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:395)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:81)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:149)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:100)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:216)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:143)
at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
at org.testng.TestRunner.privateRun(TestRunner.java:753)
at org.testng.TestRunner.run(TestRunner.java:607)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:368)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:363)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:321)
at org.testng.SuiteRunner.run(SuiteRunner.java:270)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1284)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1209)
at org.testng.TestNG.runSuites(TestNG.java:1124)
at org.testng.TestNG.run(TestNG.java:1096)
at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:132)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:193)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:94)
at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:147)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
Caused by: java.io.IOException: Error while instrumenting class com/suning/srcdas/address/business/AddressBusiness.
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrumentError(Instrumenter.java:160)
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:111)
at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:91)
... 66 more
Caused by: java.lang.IllegalStateException: Class com/suning/srcdas/address/business/AddressBusiness is already instrumented.
at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:89)
at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:55)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassVisitor.visitField(ClassVisitor.java:272)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.readField(ClassReader.java:768)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:689)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:506)
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:84)
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:108)
... 67 more
at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:93)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:424)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:250)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:401)
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1432)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1377)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:641)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:609)
at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1484)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:425)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:395)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:81)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:524)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:149)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:100)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:515)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:216)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:143)
at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
at org.testng.TestRunner.privateRun(TestRunner.java:753)
at org.testng.TestRunner.run(TestRunner.java:607)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:368)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:363)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:321)
at org.testng.SuiteRunner.run(SuiteRunner.java:270)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1284)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1209)
at org.testng.TestNG.runSuites(TestNG.java:1124)
at org.testng.TestNG.run(TestNG.java:1096)
at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:132)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:193)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:94)
at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:147)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
Caused by: java.io.IOException: Error while instrumenting class com/suning/srcdas/address/business/AddressBusiness.
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrumentError(Instrumenter.java:160)
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:111)
at org.jacoco.agent.rt.internal_6da5971.CoverageTransformer.transform(CoverageTransformer.java:91)
... 66 more
Caused by: java.lang.IllegalStateException: Class com/suning/srcdas/address/business/AddressBusiness is already instrumented.
at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:89)
at org.jacoco.agent.rt.internal_6da5971.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:55)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassVisitor.visitField(ClassVisitor.java:272)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.readField(ClassReader.java:768)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:689)
at org.jacoco.agent.rt.internal_6da5971.asm.ClassReader.accept(ClassReader.java:506)
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:84)
at org.jacoco.agent.rt.internal_6da5971.core.instr.Instrumenter.instrument(Instrumenter.java:108)
... 67 more
先要加载一个类,但是这个类的成员声明了一个对象,所以先使用ClassInstrumenter.visitField 访问成员,访问失败所以为什么
打印了Instrumenter.instrument(Instrumenter.java:111)
访问成员为什么失败,因为这个成员对象创造之前,需要先加载这个类,然后创建一个类对象,再去创建一个对象的指针。
要加载这个成员对应的类就需要read class ,因为是离线模式(on-offline)所以调用了Instrumenter.instrument input进来,然后再out出去;覆盖class文件。