All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jclasslib.agent.Communicator Maven / Gradle / Ivy

/*
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public
 License as published by the Free Software Foundation; either
 version 2 of the license, or (at your option) any later version.
 */

package org.jclasslib.agent;

import java.lang.instrument.ClassDefinition;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Communicator implements CommunicatorMBean {
    private final Instrumentation instrumentation;
    private final ModuleResolver moduleResolver = createModuleResolver();

    public Communicator(Instrumentation instrumentation) {
        this.instrumentation = instrumentation;
    }

    @Override
    public List getClasses() {
        return Arrays.stream(instrumentation.getAllLoadedClasses())
                .filter(c -> !c.isArray())
                .map(c -> new ClassDescriptor(c.getName(), moduleResolver.getModuleName(c)))
                .collect(Collectors.toList());
    }

    @Override
    public byte[] getClassFile(String fileName) {
        String className = fileName.replace('/', '.');
        return findClass(className)
                .map(this::getClassFile)
                .orElse(null);
    }

    @Override
    public ReplacementResult replaceClassFile(String fileName, byte[] bytes) {
        String className = fileName.replace('/', '.');
        Class c = findClass(className).orElse(null);
        if (c != null) {
            try {
                instrumentation.redefineClasses(new ClassDefinition(c, bytes));
                return ReplacementResult.SUCCESS;
            } catch (Throwable e) {
                return new ReplacementResult(e.getMessage());
            }
        }
        return new ReplacementResult("The class could not be found");
    }

    @SuppressWarnings("rawtypes")
    private Optional findClass(String className) {
        return Arrays.stream(instrumentation.getAllLoadedClasses())
                .filter(c -> c.getName().equals(className))
                .findFirst();
    }

    private byte[] getClassFile(Class c) {
        ReadClassFileTransformer transformer = new ReadClassFileTransformer();
        try {
            instrumentation.addTransformer(transformer, true);
            instrumentation.retransformClasses(c);
        } catch (Throwable e) {
            e.printStackTrace();
            return null;
        } finally {
            instrumentation.removeTransformer(transformer);
        }
        return transformer.bytes;
    }

    private ModuleResolver createModuleResolver() {
        try {
            if (!System.getProperty("java.version").startsWith("1.")) {
                return (ModuleResolver)Class.forName("org.jclasslib.agent.ModuleResolverImpl").getConstructor().newInstance();
            }
        } catch (Exception t) {
            t.printStackTrace();
        }
        return new NoModuleResolverImpl();
    }

    private static class ReadClassFileTransformer implements ClassFileTransformer {
        byte[] bytes;

        @Override
        public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
            if (classBeingRedefined != null) {
                this.bytes = classfileBuffer;
            }
            return null;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy