jacoco 源码分析 class字节码植入的冲突问题

首先看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 moreat 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文件。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值