diff options
author | Xin Li <delphij@google.com> | 2018-08-06 16:50:35 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2018-08-06 16:50:35 -0700 |
commit | c09ea2ab692393c0891eaefcca288ac3d19679b3 (patch) | |
tree | da5a3f23c0349b599cb891415805eda15137f9af | |
parent | 730cc2668f7a8e9ef614b7bccf4b1586e77f9e90 (diff) | |
parent | 9da9e9d2228a0f37721df5749356f026a80a791f (diff) | |
download | jacoco-c09ea2ab692393c0891eaefcca288ac3d19679b3.tar.gz |
Merge Android Pie into masterandroid-o-mr1-iot-release-1.0.3
Bug: 112104996
Change-Id: Ife26a62a004cc7153634b9e2f6ca9a1c805a91a3
7 files changed, 130 insertions, 16 deletions
@@ -17,5 +17,5 @@ LOCAL_PATH := $(call my-dir) # include jacoco-cli in the dist directory to enable running it to generate a code-coverage report ifeq ($(EMMA_INSTRUMENT),true) -$(call dist-for-goals, dist_files, $(HOST_OUT_JAVA_LIBRARIES)/jacoco-cli.jar) +$(call dist-for-goals, dist_files apps_only, $(HOST_OUT_JAVA_LIBRARIES)/jacoco-cli.jar) endif diff --git a/README.android b/README.android index cad30c6c..8fa2b902 100644 --- a/README.android +++ b/README.android @@ -14,3 +14,10 @@ is the list of the changes: 1) Remove the creation of JmxRegistration in org.jacoco.agent.rt.internal.Agent. 2) Change default OutputMode to none in org.jacoco.core.runtime.AgentOptions +3) Change the runtime to reduce dependencies on core libraries. + Previously, Offline's static initializer would eagerly create an + Agent, a process which has lots of dependencies. With this change, + Offline only eagerly creates a Map<Long, ExecutionData>, which is much + more lightweight. The Agent is only created when it's actually + needed. This makes it possible to instrument a lot of more core + libraries without creating a circular dependency at runtime. diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java index 45bc8bdc..9f9fc782 100644 --- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java +++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java @@ -37,6 +37,7 @@ import org.jacoco.core.runtime.AgentOptions.OutputMode; import org.jacoco.core.runtime.RuntimeData; import org.jacoco.core.tools.ExecFileLoader; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; /** @@ -132,6 +133,9 @@ public class AgentTest implements IExceptionLogger, IAgentOutput { } @Test + // BEGIN android-change + @Ignore + // END android-change public void startup_should_register_mbean_when_enabled() throws Exception { options.setJmx(true); Agent agent = createAgent(); diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java index 667a7d0f..b4dd0c10 100644 --- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java +++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java @@ -45,8 +45,26 @@ public class Agent implements IAgent { * @return global instance */ public static synchronized Agent getInstance(final AgentOptions options) { + // BEGIN android-change + return getInstance(options, new RuntimeData()); + // END android-change + } + + // BEGIN android-change + /** + * Returns a global instance which is already started, reusing an existing set of runtime + * data. If the method is called the first time the instance is created with the given + * options. + * + * @param options + * options to configure the instance + * @param data + * the runtime data to reuse + * @return global instance + */ + public static synchronized Agent getInstance(final AgentOptions options, RuntimeData data) { if (singleton == null) { - final Agent agent = new Agent(options, IExceptionLogger.SYSTEM_ERR); + final Agent agent = new Agent(options, IExceptionLogger.SYSTEM_ERR, data); agent.startup(); Runtime.getRuntime().addShutdownHook(new Thread() { @Override @@ -58,18 +76,26 @@ public class Agent implements IAgent { } return singleton; } + // END android-change + // BEGIN android-change /** - * Returns a global instance which is already started. If a agent has not - * been initialized before this method will fail. + * Returns a global instance which is already started. If an agent has not + * been initialized then one will be created via {@link Offline#createAgent()}. + * This will capture any data written via {@link Offline#getProbes} prior to + * this call, but not subsequently. * * @return global instance * @throws IllegalStateException * if no Agent has been started yet */ + // END android-change public static synchronized Agent getInstance() throws IllegalStateException { if (singleton == null) { - throw new IllegalStateException("JaCoCo agent not started."); + // BEGIN android-change + // throw new IllegalStateException("JaCoCo agent not started."); + singleton = Offline.createAgent(); + // END android-change } return singleton; } @@ -93,10 +119,28 @@ public class Agent implements IAgent { * logger used by this agent */ Agent(final AgentOptions options, final IExceptionLogger logger) { + // BEGIN android-change + this(options, logger, new RuntimeData()); + // END android-change + } + + // BEGIN android-change + /** + * Creates a new agent with the given agent options, reusing the given runtime data. + * + * @param options + * agent options + * @param logger + * logger used by this agent + * @param data + * the runtime data to reuse + */ + private Agent(final AgentOptions options, final IExceptionLogger logger, RuntimeData data) { this.options = options; this.logger = logger; - this.data = new RuntimeData(); + this.data = data; } + // END android-change /** * Returns the runtime data object created by this agent diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java index 8b8b40c0..7eac19fa 100644 --- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java +++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java @@ -11,8 +11,12 @@ *******************************************************************************/ package org.jacoco.agent.rt.internal; +import java.util.HashMap; +import java.util.Map; import java.util.Properties; +import org.jacoco.core.data.ExecutionData; +import org.jacoco.core.data.ExecutionDataStore; import org.jacoco.core.runtime.AgentOptions; import org.jacoco.core.runtime.RuntimeData; @@ -22,14 +26,19 @@ import org.jacoco.core.runtime.RuntimeData; */ public final class Offline { - private static final RuntimeData DATA; + // BEGIN android-change + // private static final RuntimeData DATA; + private static final Map<Long, ExecutionData> DATA = new HashMap<Long, ExecutionData>(); + // END android-change private static final String CONFIG_RESOURCE = "/jacoco-agent.properties"; - static { - final Properties config = ConfigLoader.load(CONFIG_RESOURCE, - System.getProperties()); - DATA = Agent.getInstance(new AgentOptions(config)).getData(); - } + // BEGIN android-change + // static { + // final Properties config = ConfigLoader.load(CONFIG_RESOURCE, + // System.getProperties()); + // DATA = Agent.getInstance(new AgentOptions(config)).getData(); + // } + // END android-change private Offline() { // no instances @@ -48,8 +57,41 @@ public final class Offline { */ public static boolean[] getProbes(final long classid, final String classname, final int probecount) { - return DATA.getExecutionData(Long.valueOf(classid), classname, - probecount).getProbes(); + // BEGIN android-change + // return DATA.getExecutionData(Long.valueOf(classid), classname, + // probecount).getProbes(); + synchronized (DATA) { + ExecutionData entry = DATA.get(classid); + if (entry == null) { + entry = new ExecutionData(classid, classname, probecount); + DATA.put(classid, entry); + } else { + entry.assertCompatibility(classid, classname, probecount); + } + return entry.getProbes(); + } + // END android-change } + // BEGIN android-change + /** + * Creates a default agent, using config loaded from the classpath resource and the system + * properties, and a runtime data instance populated with the execution data accumulated by + * the probes up until this call is made (subsequent probe updates will not be reflected in + * this agent). + * + * @return the new agent + */ + static Agent createAgent() { + final Properties config = ConfigLoader.load(CONFIG_RESOURCE, + System.getProperties()); + synchronized (DATA) { + ExecutionDataStore store = new ExecutionDataStore(); + for (ExecutionData data : DATA.values()) { + store.put(data); + } + return Agent.getInstance(new AgentOptions(config), new RuntimeData(store)); + } + } + // END android-change } diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java index f65142e9..155e3e88 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java @@ -47,7 +47,10 @@ public class AgentOptionsTest { assertFalse(options.getInclNoLocationClasses()); assertNull(options.getSessionId()); assertTrue(options.getDumpOnExit()); - assertEquals(AgentOptions.OutputMode.file, options.getOutput()); + // BEGIN android-change + // assertEquals(AgentOptions.OutputMode.file, options.getOutput()); + assertEquals(AgentOptions.OutputMode.none, options.getOutput()); + // END android-change assertEquals(AgentOptions.DEFAULT_ADDRESS, options.getAddress()); assertEquals(AgentOptions.DEFAULT_PORT, options.getPort()); assertNull(options.getClassDumpDir()); diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java index ff249e73..74a51dcb 100644 --- a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java +++ b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java @@ -37,10 +37,24 @@ public class RuntimeData { * Creates a new runtime. */ public RuntimeData() { - store = new ExecutionDataStore(); + // BEGIN android-change + this(new ExecutionDataStore()); + // END android-change + } + + // BEGIN android-change + /** + * Creates a new runtime, reusing an existing {@link ExecutionDataStore}. + * + * @param store + * the store to reuse + */ + public RuntimeData(ExecutionDataStore store) { + this.store = store; sessionId = "<none>"; startTimeStamp = System.currentTimeMillis(); } + // END android-change /** * Sets a session identifier for this runtime. The identifier is used when |