Skip to content

Commit

Permalink
Merge pull request apache#4273 from nbauma109/patch-4243
Browse files Browse the repository at this point in the history
Issue 4243: delete java/lang/Module and use dynamic proxy to implement Instrumentation across JDK versions…
  • Loading branch information
matthiasblaesing authored Jul 6, 2022
2 parents 191d64f + 69c8d63 commit a1b803a
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 110 deletions.
23 changes: 0 additions & 23 deletions platform/o.n.bootstrap/src/java/lang/Module.java

This file was deleted.

134 changes: 47 additions & 87 deletions platform/o.n.bootstrap/src/org/netbeans/NbInstrumentation.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import java.lang.instrument.UnmodifiableClassException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.security.ProtectionDomain;
import java.util.Collection;
import java.util.List;
Expand All @@ -41,14 +43,20 @@
*
* @author Jaroslav Tulach <[email protected]>
*/
final class NbInstrumentation implements Instrumentation {
final class NbInstrumentation implements InvocationHandler {
private static final Logger LOG = Logger.getLogger(NbInstrumentation.class.getName());
private static final Object LOCK = new Object();
private static volatile Collection<NbInstrumentation> ACTIVE;

private final List<ClassFileTransformer> transformers = new CopyOnWriteArrayList<ClassFileTransformer>();
private static final ThreadLocal<Boolean> IN = new ThreadLocal<Boolean>();

private final List<ClassFileTransformer> transformers = new CopyOnWriteArrayList<>();
private static final ThreadLocal<Boolean> IN = new ThreadLocal<>();

private final Instrumentation instrumentationProxy;

public NbInstrumentation() {
instrumentationProxy = (Instrumentation) Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] { Instrumentation.class }, this);
}

static NbInstrumentation registerAgent(ClassLoader l, String agentClassName) {
try {
return registerImpl(agentClassName, l);
Expand All @@ -57,29 +65,31 @@ static NbInstrumentation registerAgent(ClassLoader l, String agentClassName) {
return null;
}
}

static void unregisterAgent(NbInstrumentation instr) {
synchronized (LOCK) {
if (ACTIVE != null) {
Collection<NbInstrumentation> clone = new WeakSet<NbInstrumentation>(ACTIVE);
Collection<NbInstrumentation> clone = new WeakSet<>(ACTIVE);
clone.remove(instr);
ACTIVE = clone;
}
}
}

private static NbInstrumentation registerImpl(String agentClassName, ClassLoader l) throws ClassNotFoundException, IllegalArgumentException, NoSuchMethodException, SecurityException, IllegalAccessException, InvocationTargetException {
final NbInstrumentation inst = new NbInstrumentation();
synchronized (LOCK) {
if (ACTIVE == null) {
ACTIVE = new WeakSet<NbInstrumentation>();
ACTIVE = new WeakSet<>();
} else {
ACTIVE = new WeakSet<NbInstrumentation>(ACTIVE);
ACTIVE = new WeakSet<>(ACTIVE);
}
ACTIVE.add(inst);
}
Class<?> agentClass = Class.forName(agentClassName, true, l);
try {
Method m = agentClass.getMethod("agentmain", String.class, Instrumentation.class); // NOI18N
m.invoke(null, "", inst);
m.invoke(null, "", inst.getInstrumentationProxy());
} catch (NoSuchMethodException ex) {
Method m = agentClass.getMethod("agentmain", String.class); // NOI18N
m.invoke(null, "");
Expand Down Expand Up @@ -112,86 +122,36 @@ public static byte[] patchByteCode(ClassLoader l, String className, ProtectionDo
//

@Override
public void addTransformer(ClassFileTransformer transformer, boolean canRetransform) {
transformers.add(transformer);
}

@Override
public void addTransformer(ClassFileTransformer transformer) {
transformers.add(transformer);
}

@Override
public boolean removeTransformer(ClassFileTransformer transformer) {
return transformers.remove(transformer);
}

@Override
public boolean isRetransformClassesSupported() {
return false;
}

@Override
public void retransformClasses(Class<?>... classes) throws UnmodifiableClassException {
throw new UnmodifiableClassException();
}

@Override
public boolean isRedefineClassesSupported() {
return false;
}

@Override
public void redefineClasses(ClassDefinition... definitions) throws ClassNotFoundException, UnmodifiableClassException {
throw new UnmodifiableClassException();
}

@Override
public boolean isModifiableClass(Class<?> theClass) {
return false;
}

@SuppressWarnings("rawtypes")
@Override
public Class[] getAllLoadedClasses() {
return new Class[0];
}

@SuppressWarnings("rawtypes")
@Override
public Class[] getInitiatedClasses(ClassLoader loader) {
return new Class[0];
}

@Override
public long getObjectSize(Object objectToSize) {
return 42;
}

@Override
public void appendToBootstrapClassLoaderSearch(JarFile jarfile) {
}

@Override
public void appendToSystemClassLoaderSearch(JarFile jarfile) {
throw new UnsupportedOperationException();
}

@Override
public boolean isNativeMethodPrefixSupported() {
return false;
}

@Override
public void setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {
throw new UnsupportedOperationException();
}

public void redefineModule(java.lang.Module module, Set<java.lang.Module> extraReads, Map<String, Set<java.lang.Module>> extraExports, Map<String, Set<java.lang.Module>> extraOpens, Set<Class<?>> extraUses, Map<Class<?>, List<Class<?>>> extraProvides) {
throw new UnsupportedOperationException();
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "addTransformer":
return transformers.add((ClassFileTransformer) args[0]);
case "removeTransformer":
return transformers.remove(args[0]);
case "isRetransformClassesSupported":
case "isRedefineClassesSupported":
case "isModifiableClass":
case "isNativeMethodPrefixSupported":
case "isModifiableModule":
return false;
case "retransformClasses":
case "redefineClasses":
throw new UnmodifiableClassException();
case "getAllLoadedClasses":
case "getInitiatedClasses":
return new Class[0];
case "getObjectSize":
return 42;
case "appendToSystemClassLoaderSearch":
case "setNativeMethodPrefix":
case "redefineModule":
throw new UnsupportedOperationException();
default:
return null;
}
}

public boolean isModifiableModule(java.lang.Module module) {
return false;
public Instrumentation getInstrumentationProxy() {
return instrumentationProxy;
}
}

0 comments on commit a1b803a

Please sign in to comment.