byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

can I wrap a final static field value

Open carlvine500 opened this issue 1 year ago • 2 comments

we want to enhance field with annotation @WrapExecutorService:

before enhance: @WrapExecutorService private static final ExecutorService executorService1 = Executors.newSingleThreadExecutor(); after enhance: private static final ExecutorService executorService = NewExecutorService.of(Executors.newSingleThreadExecutor());

full example is following:

public class Main4 {
    public static void main(String[] args) {

    }
    @Retention(RetentionPolicy.RUNTIME)
    @Target(value = {TYPE,FIELD})
    public @interface WrapExecutorService {
    }
    public static class Example{
        @WrapExecutorService
        private static final ExecutorService executorService1 = Executors.newSingleThreadExecutor();
        private static final ExecutorService executorService2 = NewExecutorService.of(Executors.newSingleThreadExecutor());
    }

    public static class NewExecutorService implements ExecutorService {
        private ExecutorService executorService;
        public static ExecutorService of(ExecutorService executorService){
            NewExecutorService newExecutorService = new NewExecutorService();
            newExecutorService.executorService= executorService;
            return newExecutorService;
        }

        @Override
        public void shutdown() {

        }

        @Override
        public List<Runnable> shutdownNow() {
            return null;
        }

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

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

        @Override
        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
            return false;
        }

        @Override
        public <T> Future<T> submit(Callable<T> task) {
            return null;
        }

        @Override
        public <T> Future<T> submit(Runnable task, T result) {
            return null;
        }

        @Override
        public Future<?> submit(Runnable task) {
            return null;
        }

        @Override
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
            return null;
        }

        @Override
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
            return null;
        }

        @Override
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
            return null;
        }

        @Override
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            return null;
        }

        @Override
        public void execute(Runnable command) {

        }
    }

}

carlvine500 avatar Jul 27 '23 09:07 carlvine500

You would intercept via .executable(isTypeInitializer()) and in the code you add, you would read the field and write back a modified value.

raphw avatar Aug 06 '23 21:08 raphw

@raphw

field assigned with a fixed value by invokable(ElementMatchers.isTypeInitializer()) , can you show me how to read the old field value and create a new value by old field value .

public class Main4_github {
    public static void main(String[] args) {
        Instrumentation instrumentation = ByteBuddyAgent.install();
        new AgentBuilder.Default()
                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                .with(AgentBuilder.RedefinitionStrategy.Listener.StreamWriting.toSystemError())
                .with(AgentBuilder.Listener.StreamWriting.toSystemError().withTransformationsOnly())
                .with(AgentBuilder.InstallationListener.StreamWriting.toSystemError())
                .type(ElementMatchers.declaresField(isAnnotatedWith(WrapExecutorService.class))
                )
                .transform(new AgentBuilder.Transformer() {
                    @Override //
                    public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
                                                            ClassLoader classLoader, JavaModule module,
                                                            ProtectionDomain protectionDomain) {
                        FieldDescription.InDefinedShape inDefinedShape = typeDescription.getDeclaredFields().get(0);
                        ExecutorService executorServiceOld = Executors.newFixedThreadPool(2);
                        ExecutorService executorServiceNew = NewExecutorService.of(executorServiceOld);
                        return builder
                                .invokable(ElementMatchers.isTypeInitializer())
                                .intercept(FieldAccessor.of(inDefinedShape).setsValue(executorServiceNew));
                    }
                })
                .installOn(instrumentation);

        System.out.println("Example.executorService3:" + Example.executorService3);
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(value = {TYPE, FIELD, TYPE_USE})
    public @interface WrapExecutorService {
    }


    @TtlEnable
    public static class Example {
        @WrapExecutorService
        public static ExecutorService executorService3 =
                new ThreadPoolExecutor(
                        1, 1,
                        0L, TimeUnit.MILLISECONDS,
                        new LinkedBlockingQueue<Runnable>());
    }

    public static class NewExecutorService implements ExecutorService {
        private ExecutorService executorService;

        public static ExecutorService of(ExecutorService executorService) {
            NewExecutorService newExecutorService = new NewExecutorService();
            newExecutorService.executorService = executorService;
            System.out.println("ExecutorService.of(..)-->" + executorService);
            return newExecutorService;
        }

        @Override
        public void shutdown() {

        }

        @Override
        public List<Runnable> shutdownNow() {
            return null;
        }

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

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

        @Override
        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
            return false;
        }

        @Override
        public <T> Future<T> submit(Callable<T> task) {
            return null;
        }

        @Override
        public <T> Future<T> submit(Runnable task, T result) {
            return null;
        }

        @Override
        public Future<?> submit(Runnable task) {
            return null;
        }

        @Override
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
            return null;
        }

        @Override
        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
            return null;
        }

        @Override
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
            return null;
        }

        @Override
        public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            return null;
        }

        @Override
        public void execute(Runnable command) {

        }
    }

}

carlvine500 avatar Aug 10 '23 06:08 carlvine500