Search in sources :

Example 6 with UnmodifiableClassException

use of java.lang.instrument.UnmodifiableClassException in project fakereplace by fakereplace.

the class MainTransformer method transform.

@Override
public byte[] transform(final ClassLoader loader, final String className, final Class<?> classBeingRedefined, final ProtectionDomain protectionDomain, final byte[] classfileBuffer) throws IllegalClassFormatException {
    if (className == null) {
        // TODO: deal with lambdas
        return classfileBuffer;
    }
    boolean replaceable = Fakereplace.isClassReplaceable(className, loader);
    if (classBeingRedefined != null) {
        retransformationStarted = true;
        if (logClassRetransformation && replaceable) {
            log.info("Fakereplace is replacing class " + className);
        }
    }
    ChangedClassImpl changedClass = null;
    if (classBeingRedefined != null) {
        changedClass = new ChangedClassImpl(classBeingRedefined);
    }
    boolean changed = false;
    if (!replaceable && UnmodifiedFileIndex.isClassUnmodified(className)) {
        return null;
    }
    Set<Class<?>> classesToRetransform = new HashSet<>();
    final ClassFile file;
    try {
        Set<MethodInfo> modifiedMethods = new HashSet<>();
        file = new ClassFile(new DataInputStream(new ByteArrayInputStream(classfileBuffer)));
        for (final FakereplaceTransformer transformer : transformers) {
            if (transformer.transform(loader, className, classBeingRedefined, protectionDomain, file, classesToRetransform, changedClass, modifiedMethods)) {
                changed = true;
            }
        }
        if (!changed) {
            UnmodifiedFileIndex.markClassUnmodified(className);
            return null;
        } else {
            try {
                if (!modifiedMethods.isEmpty()) {
                    ClassPool classPool = new ClassPool();
                    if (loader == null) {
                        classPool.appendClassPath(new LoaderClassPath(ClassLoader.getSystemClassLoader()));
                    } else {
                        classPool.appendClassPath(new LoaderClassPath(loader));
                    }
                    classPool.appendSystemPath();
                    for (MethodInfo method : modifiedMethods) {
                        if (method.getCodeAttribute() != null) {
                            method.getCodeAttribute().computeMaxStack();
                            try {
                                method.rebuildStackMap(classPool);
                            } catch (BadBytecode e) {
                                Throwable root = e;
                                while (!(root instanceof NotFoundException) && root != null && root.getCause() != root) {
                                    root = root.getCause();
                                }
                                if (root instanceof NotFoundException) {
                                    NotFoundException cause = (NotFoundException) root;
                                    Bytecode bytecode = new Bytecode(file.getConstPool());
                                    bytecode.addNew(NoClassDefFoundError.class.getName());
                                    bytecode.add(Opcode.DUP);
                                    bytecode.addLdc(cause.getMessage());
                                    bytecode.addInvokespecial(NoClassDefFoundError.class.getName(), "<init>", "(Ljava/lang/String;)V");
                                    bytecode.add(Opcode.ATHROW);
                                    method.setCodeAttribute(bytecode.toCodeAttribute());
                                    method.getCodeAttribute().computeMaxStack();
                                    method.getCodeAttribute().setMaxLocals(DescriptorUtils.maxLocalsFromParameters(method.getDescriptor()) + 1);
                                    method.rebuildStackMap(classPool);
                                } else {
                                    throw e;
                                }
                            }
                        }
                    }
                }
            } catch (BadBytecode e) {
                throw new RuntimeException(e);
            }
            ByteArrayOutputStream bs = new ByteArrayOutputStream();
            file.write(new DataOutputStream(bs));
            // dump the class for debugging purposes
            final String dumpDir = AgentOptions.getOption(AgentOption.DUMP_DIR);
            if (dumpDir != null) {
                try {
                    File dump = new File(dumpDir + '/' + file.getName() + ".class");
                    dump.getParentFile().mkdirs();
                    FileOutputStream s = new FileOutputStream(dump);
                    DataOutputStream dos = new DataOutputStream(s);
                    file.write(dos);
                    s.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (!classesToRetransform.isEmpty()) {
                synchronized (this) {
                    retransformationOutstandingCount++;
                }
                Thread t = new Thread(() -> {
                    try {
                        Fakereplace.getInstrumentation().retransformClasses(classesToRetransform.toArray(new Class[classesToRetransform.size()]));
                    } catch (UnmodifiableClassException e) {
                        log.error("Failed to retransform classes", e);
                    } finally {
                        synchronized (MainTransformer.this) {
                            retransformationOutstandingCount--;
                            notifyAll();
                        }
                    }
                });
                t.setDaemon(true);
                t.start();
            }
            if (classBeingRedefined != null) {
                changedClasses.add(changedClass);
                queueIntegration();
            }
            return bs.toByteArray();
        }
    } catch (IOException e) {
        e.printStackTrace();
        throw new IllegalClassFormatException(e.getMessage());
    } catch (Throwable e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}
Also used : DataOutputStream(java.io.DataOutputStream) ClassPool(javassist.ClassPool) NotFoundException(javassist.NotFoundException) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) BadBytecode(javassist.bytecode.BadBytecode) Bytecode(javassist.bytecode.Bytecode) HashSet(java.util.HashSet) ClassFile(javassist.bytecode.ClassFile) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) ChangedClassImpl(org.fakereplace.replacement.notification.ChangedClassImpl) LoaderClassPath(javassist.LoaderClassPath) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) DataInputStream(java.io.DataInputStream) BadBytecode(javassist.bytecode.BadBytecode) NotFoundException(javassist.NotFoundException) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) IOException(java.io.IOException) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) ByteArrayInputStream(java.io.ByteArrayInputStream) FileOutputStream(java.io.FileOutputStream) ChangedClass(org.fakereplace.api.ChangedClass) MethodInfo(javassist.bytecode.MethodInfo) ClassFile(javassist.bytecode.ClassFile) File(java.io.File)

Example 7 with UnmodifiableClassException

use of java.lang.instrument.UnmodifiableClassException in project HotswapAgent by HotswapProjects.

the class HotSwapTool method toVersion.

/**
 * Redefines all inner classes of a outer class to a specified version. Inner classes who do not have a particular
 * representation for a version remain unchanged.
 *
 * @param outerClass
 *            the outer class whose inner classes should be redefined
 * @param versionNumber
 *            the target version number
 */
public static void toVersion(Class<?> outerClass, int versionNumber, Class<?>... extraClasses) {
    assert versionNumber >= 0;
    // if (versionNumber == getCurrentVersion(outerClass)) {
    // // Nothing to do!
    // return;
    // }
    Map<String, File> files = findClassesWithVersion(outerClass, versionNumber);
    for (Class<?> extra : extraClasses) {
        if (parseClassVersion(extra.getSimpleName()) == versionNumber) {
            String packageName = extra.getPackage().getName().replace('.', '/');
            URL url = extra.getClassLoader().getResource(packageName);
            if (url == null) {
                throw new IllegalArgumentException("Cannot find URL corresponding to the package '" + packageName + "'");
            }
            File file = new File(url.getFile(), extra.getSimpleName() + ".class");
            files.put(extra.getName(), file);
        }
    }
    try {
        Map<Class<?>, byte[]> map = buildRedefinitionMap(files);
        long startTime = System.currentTimeMillis();
        redefiner.redefineClasses(map);
        long curTime = System.currentTimeMillis() - startTime;
        totalTime += curTime;
        redefinitionCount++;
    } catch (UnmodifiableClassException e) {
        throw new UnsupportedOperationException(e);
    } catch (ClassNotFoundException e) {
        throw new RuntimeException("Cannot redefine classes", e);
    } catch (IOException e) {
        throw new RuntimeException("Cannot redefine classes", e);
    }
    setCurrentVersion(outerClass, versionNumber);
}
Also used : UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) IOException(java.io.IOException) URL(java.net.URL) File(java.io.File)

Example 8 with UnmodifiableClassException

use of java.lang.instrument.UnmodifiableClassException in project HotswapAgent by HotswapProjects.

the class InstrumentationRedefiner method redefineClasses.

public void redefineClasses(Map<Class<?>, byte[]> classes) throws ClassNotFoundException, UnmodifiableClassException {
    if (PluginManager.getInstance().getInstrumentation() == null) {
        throw new IllegalStateException("Instrumentation agent is not properly installed!");
    }
    ClassDefinition[] definitions = new ClassDefinition[classes.size()];
    int i = 0;
    for (Map.Entry<Class<?>, byte[]> entry : classes.entrySet()) {
        definitions[i++] = new ClassDefinition(entry.getKey(), entry.getValue());
        URL classResource = getClassResource(entry.getKey());
        try (OutputStream fileWriter = new FileOutputStream(new File(classResource.toURI()))) {
            fileWriter.write(entry.getValue());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    PluginManager.getInstance().getInstrumentation().redefineClasses(definitions);
}
Also used : OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) ClassDefinition(java.lang.instrument.ClassDefinition) URL(java.net.URL) IOException(java.io.IOException) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) FileOutputStream(java.io.FileOutputStream) Map(java.util.Map) File(java.io.File)

Example 9 with UnmodifiableClassException

use of java.lang.instrument.UnmodifiableClassException in project mockito by mockito.

the class InlineBytecodeGenerator method clearAllCaches.

@Override
public synchronized void clearAllCaches() {
    Set<Class<?>> types = new HashSet<>();
    mocked.forEach(types::add);
    if (types.isEmpty()) {
        return;
    }
    mocked.clear();
    flatMocked.clear();
    try {
        instrumentation.retransformClasses(types.toArray(new Class<?>[0]));
    } catch (UnmodifiableClassException e) {
        throw new MockitoException(join("Failed to reset mocks.", "", "This should not influence the working of Mockito.", "But if the reset intends to remove mocking code to improve performance, it is still impacted."), e);
    }
}
Also used : UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) MockitoException(org.mockito.exceptions.base.MockitoException)

Example 10 with UnmodifiableClassException

use of java.lang.instrument.UnmodifiableClassException in project pinpoint by naver.

the class DynamicTransformServiceTest method testRetransform_Fail_memoryleak_prevent.

@Test()
public void testRetransform_Fail_memoryleak_prevent() throws Exception {
    final Instrumentation instrumentation = mock(Instrumentation.class);
    when(instrumentation.isModifiableClass(any(Class.class))).thenReturn(true);
    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            throw new UnmodifiableClassException();
        }
    }).when(instrumentation).retransformClasses(any(Class.class));
    DefaultDynamicTransformerRegistry listener = new DefaultDynamicTransformerRegistry();
    final ClassFileTransformer classFileTransformer = mock(ClassFileTransformer.class);
    DynamicTransformService dynamicTransformService = new DynamicTransformService(instrumentation, listener);
    try {
        dynamicTransformService.retransform(String.class, classFileTransformer);
        Assert.fail("expected retransform fail");
    } catch (Exception e) {
    }
    Assert.assertEquals(listener.size(), 0);
}
Also used : ClassFileTransformer(java.lang.instrument.ClassFileTransformer) InvocationOnMock(org.mockito.invocation.InvocationOnMock) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) Instrumentation(java.lang.instrument.Instrumentation) UnmodifiableClassException(java.lang.instrument.UnmodifiableClassException) Test(org.junit.Test)

Aggregations

UnmodifiableClassException (java.lang.instrument.UnmodifiableClassException)10 File (java.io.File)3 IOException (java.io.IOException)3 ClassDefinition (java.lang.instrument.ClassDefinition)3 HashSet (java.util.HashSet)3 FileOutputStream (java.io.FileOutputStream)2 ClassFileTransformer (java.lang.instrument.ClassFileTransformer)2 Instrumentation (java.lang.instrument.Instrumentation)2 URL (java.net.URL)2 Test (org.junit.Test)2 MockitoException (org.mockito.exceptions.base.MockitoException)2 InvocationOnMock (org.mockito.invocation.InvocationOnMock)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 DataInputStream (java.io.DataInputStream)1 DataOutputStream (java.io.DataOutputStream)1 OutputStream (java.io.OutputStream)1 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)1 Map (java.util.Map)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1