Skip to content

Commit

Permalink
(WIP) (PoC) Agent should not open java.base module to unnamed modul…
Browse files Browse the repository at this point in the history
…e of the application class loader
  • Loading branch information
Godin committed Jun 25, 2022
1 parent 1a2ac91 commit e69755a
Showing 1 changed file with 34 additions and 17 deletions.
51 changes: 34 additions & 17 deletions org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/PreMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@
*******************************************************************************/
package org.jacoco.agent.rt.internal;

import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.Instrumentation;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import org.jacoco.core.internal.InputStreams;
import org.jacoco.core.runtime.AgentOptions;
import org.jacoco.core.runtime.IRuntime;
import org.jacoco.core.runtime.InjectedClassRuntime;
Expand Down Expand Up @@ -58,31 +61,46 @@ public static void premain(final String options, final Instrumentation inst)
private static IRuntime createRuntime(final Instrumentation inst)
throws Exception {

if (redefineJavaBaseModule(inst)) {
return new InjectedClassRuntime(Object.class, "$JaCoCo");
final IRuntime injectedClassRuntime = createInjectedClassRuntime(inst);
if (injectedClassRuntime != null) {
return injectedClassRuntime;
}

return ModifiedSystemClassRuntime.createFor(inst,
"java/lang/UnknownError");
}

/**
* Opens {@code java.base} module for {@link InjectedClassRuntime} when
* executed on Java 9 JREs or higher.
*
* @return <code>true</code> when running on Java 9 or higher,
* <code>false</code> otherwise
* @throws Exception
* if unable to open
*/
private static boolean redefineJavaBaseModule(
private static IRuntime createInjectedClassRuntime(
final Instrumentation instrumentation) throws Exception {
try {
Class.forName("java.lang.Module");
} catch (final ClassNotFoundException e) {
return false;
return null;
}
final IRuntime runtime = (IRuntime) (new ClassLoader() {
@Override
public Class<?> loadClass(String name)
throws ClassNotFoundException {
if (!name.startsWith(InjectedClassRuntime.class.getName())) {
return super.loadClass(name);
}
final InputStream resourceAsStream = getResourceAsStream(
name.replace('.', '/') + ".class");
final byte[] bytes;
try {
bytes = InputStreams.readFully(resourceAsStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
return defineClass(name, bytes, 0, bytes.length);
}
}.loadClass(InjectedClassRuntime.class.getName())
.getConstructor(Class.class, String.class)
.newInstance(Object.class, "$JaCoCo"));
final Object module = getModule(runtime.getClass());
if (module.equals(getModule(PreMain.class))) {
throw new IllegalStateException();
}

Instrumentation.class.getMethod("redefineModule", //
Class.forName("java.lang.Module"), //
Set.class, //
Expand All @@ -95,12 +113,11 @@ private static boolean redefineJavaBaseModule(
Collections.emptySet(), // extraReads
Collections.emptyMap(), // extraExports
Collections.singletonMap("java.lang",
Collections.singleton(
getModule(InjectedClassRuntime.class))), // extraOpens
Collections.singleton(module)), // extraOpens
Collections.emptySet(), // extraUses
Collections.emptyMap() // extraProvides
);
return true;
return runtime;
}

/**
Expand Down

0 comments on commit e69755a

Please sign in to comment.