下面列出了java.lang.NoSuchMethodException#java.lang.instrument.UnmodifiableClassException 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private boolean instrument(String source, Location realLocation, ResolvedSourceLocation location) throws UnmodifiableClassException, ClassNotFoundException {
if (instrumented.contains(realLocation)) {
return true;
}
ClassFileTransformer transformer = new DebuggerClassFileTransformer(instrumentInfo.getClassFileBuffer(), source, location);
try {
Class<?> clazz = instrumentInfo.signatureToClass(location.getClassSignature());
inst.addTransformer(transformer, true);
inst.retransformClasses(clazz);
instrumented.add(realLocation);
instrumentInfo.addTransformedClasses(clazz);
return true;
} finally {
inst.removeTransformer(transformer);
}
}
public static void agentmain(String agentArgs, Instrumentation inst)
throws ClassNotFoundException, UnmodifiableClassException,
InterruptedException {
final ColaTransformer transformer = new ColaTransformer(convert(agentArgs));
if(!isLock(transformer)){
return;
}
try {
inst.addTransformer(transformer, true);
Set<Class<?>> oriClassSet = searchClass(inst, transformer.getArgs().getClassName(), 1000);
final Class<?>[] classArray = new Class<?>[oriClassSet.size()];
System.arraycopy(oriClassSet.toArray(), 0, classArray, 0, oriClassSet.size());
inst.retransformClasses(classArray);
}finally {
inst.removeTransformer(transformer);
}
System.out.println("agentmain DONE");
}
protected void init(boolean retransformBootstrapped) {
// Add self as transfomer
inst.addTransformer(this, inst.isRetransformClassesSupported());
// Retransform all non-ignored classes
if (retransformBootstrapped && inst.isRetransformClassesSupported()) {
List<Class<?>> classesToRetransform = new ArrayList<>();
for (Class<?> cls : inst.getAllLoadedClasses()) {
if (inst.isModifiableClass(cls) && !isClassIgnored(cls)) classesToRetransform.add(cls);
}
if (!classesToRetransform.isEmpty()) {
try {
inst.retransformClasses(classesToRetransform.toArray(new Class<?>[classesToRetransform.size()]));
} catch (UnmodifiableClassException e) {
System.out.println("Failed retransforming classes: " + e);
}
}
}
}
public static void premain(String args, Instrumentation instrumentation) {
if (!instrumentation.isRetransformClassesSupported()) {
System.out.println("Class retransformation is not supported.");
return;
}
System.out.println("Calling lambda to ensure that lambda forms were created");
Agent.lambda.run();
System.out.println("Registering class file transformer");
instrumentation.addTransformer(new Agent());
for (Class c : instrumentation.getAllLoadedClasses()) {
if (c.getName().contains("LambdaForm") &&
instrumentation.isModifiableClass(c)) {
System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
try {
instrumentation.retransformClasses(c);
} catch (UnmodifiableClassException e) {
throw new AssertionError("Modification of modifiable class " +
"caused UnmodifiableClassException", e);
}
}
}
}
/**
* Saves changed by retransforming classes.
*
* @throws ClassNotFoundException
* When the modified class couldn't be found.
* @throws UnmodifiableClassException
* When the modified class is not allowed to be modified.
* @throws ClassFormatError
* When the modified class is not valid.
*/
public void save() throws ClassNotFoundException, UnmodifiableClassException, ClassFormatError {
// Classes to update
Set<String> dirty = new HashSet<>(getDirtyClasses());
if(dirty.isEmpty()) {
Log.info("There are no classes to redefine.", dirty.size());
return;
}
Log.info("Preparing to redefine {} classes", dirty.size());
ClassDefinition[] definitions = new ClassDefinition[dirty.size()];
int i = 0;
for (String name : dirty) {
String clsName = name.replace('/', '.');
Class<?> cls = Class.forName(clsName, false, ClasspathUtil.scl);
byte[] value = getClasses().get(name);
if (value == null)
throw new IllegalStateException("Failed to fetch code for class: " + name);
definitions[i] = new ClassDefinition(cls, value);
i++;
}
// Apply new definitions
instrumentation.redefineClasses(definitions);
// We don't want to continually re-apply changes that don't need to be updated
getDirtyClasses().clear();
Log.info("Successfully redefined {} classes", definitions.length);
}
@Test
public void testBadModification2() throws ClassNotFoundException, AgentLoadException, AgentInitializationException, IOException, AttachNotSupportedException, UnmodifiableClassException, IllegalConnectorArgumentsException {
// Rewrite method
DynamicModification badModification = new DynamicModification() {
public Collection<String> affects() {
return Lists.newArrayList(TestJDWPAgentDebug.class.getName());
}
public void apply(ClassPool arg0) throws NotFoundException, CannotCompileException {
CtClass cls = arg0.getCtClass(TestJDWPAgentDebug.class.getName());
cls.getMethods()[0].insertBefore("definitely not code...");
}
};
JDWPAgent dynamic = JDWPAgent.get();
// Modification should just be ignored since it throws a notfoundexception
try {
dynamic.install(badModification);
fail();
} catch (CannotCompileException e) {
}
}
@Test
public void testBadModification2() throws ClassNotFoundException, AgentLoadException, AgentInitializationException, IOException, AttachNotSupportedException, UnmodifiableClassException {
// Rewrite method
DynamicModification badModification = new DynamicModification() {
public Collection<String> affects() {
return Lists.newArrayList(TestJVMAgent.class.getName());
}
public void apply(ClassPool arg0) throws NotFoundException, CannotCompileException {
CtClass cls = arg0.getCtClass(TestJVMAgent.class.getName());
cls.getMethods()[0].insertBefore("definitely not code...");
}
};
JVMAgent dynamic = JVMAgent.get();
// Modification should just be ignored since it throws a notfoundexception
try {
dynamic.install(badModification);
fail();
} catch (CannotCompileException e) {
}
}
@Test
public void testBadTracepoint() throws ClassNotFoundException, UnmodifiableClassException, CannotCompileException {
// Create and register dummy advice
PTAgentForTest test = new PTAgentForTest();
AdviceImplForTest advice = new AdviceImplForTest();
int lookupId = test.agent.adviceManager.register(advice);
// Method under test
MethodTracepointSpec t1 = TracepointsTestUtils.getMethodSpec(getClass(), "method");
MethodTracepointSpec tbad = MethodTracepointSpec.newBuilder(t1).setMethodName("badmethod").build();
// Invoke method - should do nothing before rewrite
method("hi");
advice.expectSize(0);
// Rewrite method
MethodRewriteModification mod = new MethodRewriteModification(tbad, lookupId);
test.agent.dynamic.clear().add(mod).install();
advice.expectSize(0);
method("hi");
advice.expectSize(0);
}
/**
* Ensures that the given sampler will be invoked every time a constructor for class c is invoked.
*
* @param c The class to be tracked
* @param sampler the code to be invoked when an instance of c is constructed
* @throws UnmodifiableClassException if c cannot be modified.
*/
public static void instrumentClass(Class<?> c, ConstructorCallback<?> sampler)
throws UnmodifiableClassException {
// IMPORTANT: Don't forget that other threads may be accessing this
// class while this code is running. Specifically, the class may be
// executed directly after the retransformClasses is called. Thus, we need
// to be careful about what happens after the retransformClasses call.
synchronized (samplerPutAtomicityLock) {
List<ConstructorCallback<?>> list = samplerMap.get(c);
if (list == null) {
CopyOnWriteArrayList<ConstructorCallback<?>> samplerList =
new CopyOnWriteArrayList<ConstructorCallback<?>>();
samplerList.add(sampler);
samplerMap.put(c, samplerList);
Instrumentation inst = AllocationRecorder.getInstrumentation();
Class<?>[] cs = new Class<?>[1];
cs[0] = c;
inst.retransformClasses(c);
} else {
list.add(sampler);
}
}
}
/** {@inheritDoc} */
@Override
public byte[] transform(
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
if ((classBeingRedefined == null) || (!samplerMap.containsKey(classBeingRedefined))) {
return null;
}
if (!AllocationInstrumenter.canRewriteClass(className, loader)) {
throw new RuntimeException(new UnmodifiableClassException("cannot instrument " + className));
}
return instrument(classfileBuffer, classBeingRedefined);
}
/** Inserts the appropriate INVOKESTATIC call */
@Override
public void visitInsn(int opcode) {
if ((opcode == Opcodes.ARETURN)
|| (opcode == Opcodes.IRETURN)
|| (opcode == Opcodes.LRETURN)
|| (opcode == Opcodes.FRETURN)
|| (opcode == Opcodes.DRETURN)) {
throw new RuntimeException(
new UnmodifiableClassException("Constructors are supposed to return void"));
}
if (opcode == Opcodes.RETURN) {
super.visitVarInsn(Opcodes.ALOAD, 0);
super.visitMethodInsn(
Opcodes.INVOKESTATIC,
"com/google/monitoring/runtime/instrumentation/ConstructorInstrumenter",
"invokeSamplers",
"(Ljava/lang/Object;)V",
false);
}
super.visitInsn(opcode);
}
@Test
public void testThreads() throws UnmodifiableClassException {
final BasicFunctions bf = new BasicFunctions();
ConstructorInstrumenter.instrumentClass(
Thread.class,
new ConstructorCallback<Thread>() {
@Override
public void sample(Thread t) {
bf.count++;
}
});
int numThreads = 10;
for (int i = 0; i < numThreads; i++) {
Thread unused = new Thread();
}
assertEquals("Did not see correct number of Threads", numThreads, bf.count);
}
@Test
public void testBasicFunctionality() throws UnmodifiableClassException {
final BasicFunctions bf = new BasicFunctions();
ConstructorInstrumenter.instrumentClass(
BasicFunctions.class,
new ConstructorCallback<BasicFunctions>() {
@Override
public void sample(BasicFunctions newBf) {
bf.count++;
}
});
int numBFs = 10;
for (int i = 0; i < numBFs; i++) {
BasicFunctions unused = new BasicFunctions();
}
assertEquals("Did not see correct number of BasicFunctions", numBFs, bf.count);
}
@Test
public void testSubclassesAlso() throws UnmodifiableClassException {
final BasicFunctions bf = new BasicFunctions();
ConstructorInstrumenter.instrumentClass(
BasicFunctions.class,
new ConstructorCallback<BasicFunctions>() {
@Override
public void sample(BasicFunctions newBf) {
bf.count++;
}
});
int numBFs = 2;
new SubclassOfBasicFunctions();
new BasicFunctions() {};
assertEquals("Did not see correct number of BasicFunctions", numBFs, bf.count);
}
/**
* 重新热加载Class
* @param clazzDefines 有过变更的文件信息
* @throws UnmodifiableClassException 不可修改的 Class 异常
* @throws ClassNotFoundException Class未找到异常
*/
public static void reloadClass(Map<Class, byte[]> clazzDefines) throws UnmodifiableClassException, ClassNotFoundException {
for(Map.Entry<Class, byte[]> clazzDefine : clazzDefines.entrySet()){
Class clazz = clazzDefine.getKey();
byte[] classBytes = clazzDefine.getValue();
ClassDefinition classDefinition = new ClassDefinition(clazz, classBytes);
try {
Logger.info("[HOTSWAP] class:" + clazz + " will reload.");
TEnv.instrumentation.redefineClasses(classDefinition);
} catch (Exception e) {
Logger.error("[HOTSWAP] class:" + clazz + " reload failed", e);
}
}
}
/**
* 重置指定的Class
*
* @param inst inst
* @param classNameMatcher 类名匹配
* @return 增强影响范围
* @throws UnmodifiableClassException
*/
public static synchronized EnhancerAffect reset(
final Instrumentation inst,
final Matcher classNameMatcher) throws UnmodifiableClassException {
final EnhancerAffect affect = new EnhancerAffect();
final Set<Class<?>> enhanceClassSet = new HashSet<Class<?>>();
for (Class<?> classInCache : classBytesCache.keySet()) {
if (classNameMatcher.matching(classInCache.getName())) {
enhanceClassSet.add(classInCache);
}
}
final ClassFileTransformer resetClassFileTransformer = new ClassFileTransformer() {
@Override
public byte[] transform(
ClassLoader loader,
String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
return null;
}
};
try {
enhance(inst, resetClassFileTransformer, enhanceClassSet);
logger.info("Success to reset classes: " + enhanceClassSet);
} finally {
for (Class<?> resetClass : enhanceClassSet) {
classBytesCache.remove(resetClass);
affect.cCnt(1);
}
}
return affect;
}
public static void enhance(Instrumentation inst, ClassFileTransformer transformer, Set<Class<?>> classes)
throws UnmodifiableClassException {
try {
inst.addTransformer(transformer, true);
int size = classes.size();
Class<?>[] classArray = new Class<?>[size];
arraycopy(classes.toArray(), 0, classArray, 0, size);
if (classArray.length > 0) {
inst.retransformClasses(classArray);
}
} finally {
inst.removeTransformer(transformer);
}
}
private boolean instrument(String source, ResolvedSourceLocation location, final int line) throws UnmodifiableClassException, ClassNotFoundException {
ClassFileTransformer transformer = new MonitorClassFileTransformer(classFileBuffer, source, location, line);
try {
Class<?> clazz = instrumentInfo.signatureToClass(location.getClassSignature());
inst.addTransformer(transformer, true);
inst.retransformClasses(clazz);
instrumentInfo.addTransformedClasses(clazz);
return true;
} finally {
inst.removeTransformer(transformer);
}
}
private void testTransformAndVerify()
throws NoSuchFieldException, NoSuchMethodException {
Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
Class<?> myClass = c;
/*
* Verify that the expected annotations are where they should be before transform.
*/
verifyClassTypeAnnotations(c);
verifyFieldTypeAnnotations(c);
verifyMethodTypeAnnotations(c);
try {
inst.addTransformer(new Transformer(), true);
inst.retransformClasses(myClass);
} catch (UnmodifiableClassException e) {
throw new RuntimeException(e);
}
/*
* Verify that the expected annotations are where they should be after transform.
* Also verify that before and after are equal.
*/
verifyClassTypeAnnotations(c);
verifyFieldTypeAnnotations(c);
verifyMethodTypeAnnotations(c);
}
private void testTransformAndVerify()
throws NoSuchFieldException, NoSuchMethodException {
Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
Class<?> myClass = c;
/*
* Verify that the expected annotations are where they should be before transform.
*/
verifyClassTypeAnnotations(c);
verifyFieldTypeAnnotations(c);
verifyMethodTypeAnnotations(c);
try {
inst.addTransformer(new Transformer(), true);
inst.retransformClasses(myClass);
} catch (UnmodifiableClassException e) {
throw new RuntimeException(e);
}
/*
* Verify that the expected annotations are where they should be after transform.
* Also verify that before and after are equal.
*/
verifyClassTypeAnnotations(c);
verifyFieldTypeAnnotations(c);
verifyMethodTypeAnnotations(c);
}
private void testTransformAndVerify()
throws NoSuchFieldException, NoSuchMethodException {
Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
Class<?> myClass = c;
/*
* Verify that the expected annotations are where they should be before transform.
*/
verifyClassTypeAnnotations(c);
verifyFieldTypeAnnotations(c);
verifyMethodTypeAnnotations(c);
try {
inst.addTransformer(new Transformer(), true);
inst.retransformClasses(myClass);
} catch (UnmodifiableClassException e) {
throw new RuntimeException(e);
}
/*
* Verify that the expected annotations are where they should be after transform.
* Also verify that before and after are equal.
*/
verifyClassTypeAnnotations(c);
verifyFieldTypeAnnotations(c);
verifyMethodTypeAnnotations(c);
}
public static void reTransform(Class<?> clazz, byte[] classFile) throws UnmodifiableClassException {
SimpleClassFileTransformer transformer = new SimpleClassFileTransformer(clazz.getClassLoader(), clazz.getName(),
classFile);
InstrumentationHolder.instance.addTransformer(transformer, true);
InstrumentationHolder.instance.retransformClasses(clazz);
InstrumentationHolder.instance.removeTransformer(transformer);
}
/**
* 重置指定的Class
*
* @param inst inst
* @param classNameMatcher 类名匹配
* @return 增强影响范围
* @throws UnmodifiableClassException
*/
public static synchronized EnhancerAffect reset(final Instrumentation inst, final Matcher classNameMatcher)
throws UnmodifiableClassException {
final EnhancerAffect affect = new EnhancerAffect();
final Set<Class<?>> enhanceClassSet = new HashSet<Class<?>>();
for (Class<?> classInCache : classBytesCache.keySet()) {
if (classNameMatcher.matching(classInCache.getName())) {
enhanceClassSet.add(classInCache);
}
}
final ClassFileTransformer resetClassFileTransformer = new ClassFileTransformer() {
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
return null;
}
};
try {
enhance(inst, resetClassFileTransformer, enhanceClassSet);
logger.info("Success to reset classes: " + enhanceClassSet);
} finally {
for (Class<?> resetClass : enhanceClassSet) {
classBytesCache.remove(resetClass);
affect.cCnt(1);
}
}
return affect;
}
private static void enhance(Instrumentation inst, ClassFileTransformer transformer, Set<Class<?>> classes)
throws UnmodifiableClassException {
try {
inst.addTransformer(transformer, true);
int size = classes.size();
Class<?>[] classArray = new Class<?>[size];
arraycopy(classes.toArray(), 0, classArray, 0, size);
if (classArray.length > 0) {
inst.retransformClasses(classArray);
}
} finally {
inst.removeTransformer(transformer);
}
}
private Map<Class<?>, File> dump(Instrumentation inst, Set<Class<?>> classes) throws UnmodifiableClassException {
ClassDumpTransformer transformer = null;
if (directory != null) {
transformer = new ClassDumpTransformer(classes, new File(directory));
} else {
transformer = new ClassDumpTransformer(classes);
}
InstrumentationUtils.retransformClasses(inst, transformer, classes);
return transformer.getDumpResult();
}
public void process(Class<?> ... transformerClasses) {
List<AgentJob> agentJobs = new ArrayList<>();
for (Class<?> clazz : transformerClasses)
agentJobs.add(new AgentJob(clazz));
ClassTransformer classTransformer = new ClassTransformer(agentJobs);
instrumentation.addTransformer(classTransformer, true);
try {
instrumentation.retransformClasses(classTransformer.getClassesToTransform());
} catch (UnmodifiableClassException e) {
e.printStackTrace();
}
}
public static void agentmain(String agentArgs, Instrumentation instrumentation)
throws ClassNotFoundException, UnmodifiableClassException,
InterruptedException {
inst = instrumentation;
inst.addTransformer(new CodeTransformer(), true);
}
public synchronized static void removeMetricsClass(String name) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, UnmodifiableClassException {
Class seleClass = Class.forName(name.replace('/', '.'));
needRecoverClasses.put(name, needMetricsClasses.remove(name));
Instrumentation inst = instrumentation();
inst.retransformClasses(seleClass);
MetricsCollector.getCollector().removeClassMetrics(name);
}
public static void restoreClass(ViewASMCodeReq req) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, UnmodifiableClassException, IllegalAccessException, NotFoundException {
DebugInfo debugInfo = AgentTool.getDebugInfoByClassName(req.className);
if(debugInfo != null){
AgentTool.removeDebugClassByTraceId(debugInfo.getTraceId(),true);
}else {
AgentTool.removeMetricsClass(req.className);
}
}
@Override
public void redefine(ClassBytecodes[] cbcs) throws ClassInstallException, NotImplementedException, EngineTerminationException {
int count = cbcs.length;
boolean[] status = new boolean[cbcs.length];
int success = 0;
NbRemoteLoader ldr = prepareClassLoader();
for (int i = 0; i < count; i++) {
String name = cbcs[i].name();
byte[] replaceBytecode = cbcs[i].bytecodes();
Long id = ldr.getClassId(name);
if (id != null) {
Class defined = ldr.getClassOfId(id);
try {
agent.getInstrumentation().redefineClasses(
new ClassDefinition(defined, replaceBytecode)
);
status[i] = true;
success++;
} catch (ClassNotFoundException | UnmodifiableClassException ex) {
Logger.getLogger(AgentWorker.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (success < count) {
throw new ClassInstallException("Could not redefine classes", status);
}
}
}