luceat-lux-vestra
luceat-lux-vestra

Reputation: 408

Trying to implement interface and override java.lang.String with Byte Buddy

I tried with this example especially designed for ignored by byte-buddy.

I solved errors, and it looks like working with this code.

new AgentBuilder.Default()
      .with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
      .ignore(ElementMatchers.none())
      .type((ElementMatchers.named("String")))
      .transform((builder, typeDescription, classLoader, module) -> builder
        .implement(AutoCloseable.class)
        .method(named("close"))
        .intercept(Advice.to(closeInterceptor.class))
      ).installOn(instrumentation);

and my interceptor looks like this. I did System.out.print something in the interceptor,
but nothing happens over time.
(FYI, my logger setting was bad and caused an error. I deleted logger things and just used System.out.println

class closeInterceptor {

  public void intercept(@Origin Class<?> type) {
    try {
      Field field = type.getDeclaredField("value");
      field.setAccessible(true);
      Object ref = field.get(null);
      // I'm trying to deal with `java.lang.String`s internal character storage.
    } catch (NoSuchFieldException | IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }
}

Is there a way to confirm that it's working well?

Thanks in advance. (I forgot to say Happy new year!)


The default example looks like it is working at first, but look at this log.

Disconnected with this error Application Server was not connected before run configuration stop, reason: Unable to ping server at localhost:1099

I changed the port number randomly, but no effect and the same error occurred.

Please help!

Connected to the target VM, address: '127.0.0.1:49960', transport: 'socket'
Agent for instrument ignored class like java class 
method private static void sun.management.Agent.readConfiguration(java.lang.String,java.util.Properties)
method public static java.util.Properties sun.management.Agent.loadManagementProperties()
.
.
.
method public static final long java.util.zip.ZipUtils.get32(byte[],int)
Disconnected from the target VM, address: '127.0.0.1:49960', transport: 'socket'
Disconnected from server

Here is the log.

Agent for instrument ignored class like java class 
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:386)
    at sun.instrument.InstrumentationImpl.loadClassAndCallPremain(InstrumentationImpl.java:401)
Caused by: java.lang.IllegalArgumentException: None of [] allows for delegation from public abstract void java.lang.AutoCloseable.close() throws java.lang.Exception
    at net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor.bind(MethodDelegationBinder.java:1026)
    at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1051)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:620)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:609)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:526)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$RedefinitionClassVisitor.visitEnd(TypeWriter.java:3865)
    at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:702)
    at net.bytebuddy.jar.asm.ClassReader.accept(ClassReader.java:500)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining.create(TypeWriter.java:2941)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:1633)
    at net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder.make(RedefinitionDynamicTypeBuilder.java:171)
    at net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder.make(AbstractInliningDynamicTypeBuilder.java:92)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:2639)
    at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:2741)
    at com.github.shehanperera.ignored.Agent.premain(Agent.java:43)
    ... 6 more
Exception in thread "main" FATAL ERROR in native method: processing of -javaagent failed
Disconnected from the target VM, address: '127.0.0.1:49960', transport: 'socket'
Disconnected from server

Here is My premain.

public static void premain(String arguments,
  Instrumentation instrumentation) {

  System.out.println("Agent for instrument ignored class like java class ");

  ByteBuddyAgent.install();
  new ByteBuddy()
    .ignore(ElementMatchers.none())
    .redefine(String.class)
    .ignoreAlso(ElementMatchers.none())
    .implement(AutoCloseable.class)
    .method(named("close"))
    .intercept(MethodDelegation.to(closeInterceptor.class))
    .make()
    .load(ClassLoader.getSystemClassLoader())
    .getLoaded();


  new AgentBuilder.Default()
    .with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
    .ignore(ElementMatchers.none())
    .type((ElementMatchers.any()))
    .transform((builder, typeDescription, classLoader, module) -> builder
      .method(ElementMatchers.any())
      .intercept(Advice.to(IgnoreClass.class))
    ).installOn(instrumentation);

}

And finally, my interceptor.

class closeInterceptor {

  private final Logger logger = LoggerFactory.getLogger(closeInterceptor.class);
  public void intercept(@Origin Class<?> type) {
    try {
      Field field = type.getDeclaredField("value");
      field.setAccessible(true);
      Object ref = field.get(null);
      // I'm trying to deal with `java.lang.String`s internal character storage.
    } catch (NoSuchFieldException | IllegalAccessException e) {
      throw new RuntimeException(e);
    }
  }
}

I don't know about byte code manipulation well also byte buddy.

It's hard to find some reference...

Please help.

I just tried to make Java.lang.String implements AutoCloseable
and Override the close method with java agent and byte buddy.

I hope so it can be.

But I can't solve that error and exception.

Upvotes: 1

Views: 641

Answers (1)

Rafael Winterhalter
Rafael Winterhalter

Reputation: 44032

To begin with, you would need to specify java.lang.String as name, not just String.

However, it is not possible to change the shape of classes that are already loaded. Therefore, you are not able to add an interface to a class like String which will always be loaded upon agent startup with Byte Buddy.

Upvotes: 1

Related Questions