Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

muzzle.mismatch="datadog.trace.instrumentation.springweb.DatadogByteArrayOutputStream:36 Missing class B" #7842

Open
lrwh opened this issue Oct 28, 2024 · 0 comments

Comments

@lrwh
Copy link

lrwh commented Oct 28, 2024

I have created a custom class that inherits from the OutputStream class, and when the application starts and loads, a Missing class B exception occurs. I am not sure what class B is, could you help me take a look?

[dd.trace 2024-10-28 18:15:26:999 +0800] [main] DEBUG datadog.trace.agent.tooling.muzzle.MuzzleCheck - Muzzled mismatch - instrumentation.names=[spring-web] instrumentation.class=datadog.trace.instrumentation.springweb.DispatcherServletInstrumentation instrumentation.target.classloader=jdk.internal.loader.ClassLoaders$AppClassLoader@512ddf17 muzzle.mismatch="datadog.trace.instrumentation.springweb.DatadogByteArrayOutputStream:36 Missing class B"

line 36

if (this.buffers.peekLast() == null || (this.buffers.getLast()).length == this.index) {

Image

code DatadogByteArrayOutputStream

package datadog.trace.instrumentation.springweb;


import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;

public class DatadogByteArrayOutputStream extends OutputStream {
  private static final int DEFAULT_BLOCK_SIZE = 256;
  private final Deque<byte[]> buffers = new ArrayDeque();
  private final int initialBlockSize;
  private int nextBlockSize;
  private int alreadyBufferedSize;
  private int index;
  private boolean closed;

  public DatadogByteArrayOutputStream() {
    this(256);
  }

  public DatadogByteArrayOutputStream(int initialBlockSize) {
    this.nextBlockSize = 0;
    this.alreadyBufferedSize = 0;
    this.index = 0;
    this.closed = false;
    this.initialBlockSize = initialBlockSize;
    this.nextBlockSize = initialBlockSize;
  }

  public void write(int datum) throws IOException {
    if (this.closed) {
      throw new IOException("Stream closed");
    } else {
      if (this.buffers.peekLast() == null || (this.buffers.getLast()).length == this.index) {
        this.addBuffer(1);
      }

      (this.buffers.getLast())[this.index++] = (byte)datum;
    }
  }

  public void write(byte[] data, int offset, int length) throws IOException {
    if (offset >= 0 && offset + length <= data.length && length >= 0) {
      if (this.closed) {
        throw new IOException("Stream closed");
      } else {
        if (this.buffers.peekLast() == null || ((byte[])this.buffers.getLast()).length == this.index) {
          this.addBuffer(length);
        }

        if (this.index + length > ((byte[])this.buffers.getLast()).length) {
          int pos = offset;

          do {
            if (this.index == ((byte[])this.buffers.getLast()).length) {
              this.addBuffer(length);
            }

            int copyLength = ((byte[])this.buffers.getLast()).length - this.index;
            if (length < copyLength) {
              copyLength = length;
            }

            System.arraycopy(data, pos, this.buffers.getLast(), this.index, copyLength);
            pos += copyLength;
            this.index += copyLength;
            length -= copyLength;
          } while(length > 0);
        } else {
          System.arraycopy(data, offset, this.buffers.getLast(), this.index, length);
          this.index += length;
        }

      }
    } else {
      throw new IndexOutOfBoundsException();
    }
  }

  public void close() {
    this.closed = true;
  }

  public String toString() {
    return new String(this.toByteArrayUnsafe());
  }

  public int size() {
    return this.alreadyBufferedSize + this.index;
  }

  public byte[] toByteArrayUnsafe() {
    int totalSize = this.size();
    if (totalSize == 0) {
      return new byte[0];
    } else {
      this.resize(totalSize);
      return (byte[])this.buffers.getFirst();
    }
  }

  public byte[] toByteArray() {
    byte[] bytesUnsafe = this.toByteArrayUnsafe();
    return (byte[])bytesUnsafe.clone();
  }

  public void reset() {
    this.buffers.clear();
    this.nextBlockSize = this.initialBlockSize;
    this.closed = false;
    this.index = 0;
    this.alreadyBufferedSize = 0;
  }

  public void writeTo(OutputStream out) throws IOException {
    Iterator<byte[]> it = this.buffers.iterator();

    while(it.hasNext()) {
      byte[] bytes = (byte[])it.next();
      if (it.hasNext()) {
        out.write(bytes, 0, bytes.length);
      } else {
        out.write(bytes, 0, this.index);
      }
    }

  }

  public void resize(int targetCapacity) {
    if (this.buffers.peekFirst() == null) {
      this.nextBlockSize = targetCapacity - this.size();
    } else if (this.size() != targetCapacity || ((byte[])this.buffers.getFirst()).length != targetCapacity) {
      int totalSize = this.size();
      byte[] data = new byte[targetCapacity];
      int pos = 0;
      Iterator<byte[]> it = this.buffers.iterator();

      while(it.hasNext()) {
        byte[] bytes = (byte[])it.next();
        if (it.hasNext()) {
          System.arraycopy(bytes, 0, data, pos, bytes.length);
          pos += bytes.length;
        } else {
          System.arraycopy(bytes, 0, data, pos, this.index);
        }
      }

      this.buffers.clear();
      this.buffers.add(data);
      this.index = totalSize;
      this.alreadyBufferedSize = 0;
    }

  }

  private void addBuffer(int minCapacity) {
    if (this.buffers.peekLast() != null) {
      this.alreadyBufferedSize += this.index;
      this.index = 0;
    }

    if (this.nextBlockSize < minCapacity) {
      this.nextBlockSize = nextPowerOf2(minCapacity);
    }

    this.buffers.add(new byte[this.nextBlockSize]);
    this.nextBlockSize *= 2;
  }

  private static int nextPowerOf2(int val) {
    --val;
    val |= val >> 1;
    val |= val >> 2;
    val |= val >> 4;
    val |= val >> 8;
    val |= val >> 16;
    ++val;
    return val;
  }
}

DispatcherServletInstrumentation class add helperClassNames

@AutoService(InstrumenterModule.class)
public final class DispatcherServletInstrumentation extends InstrumenterModule.Tracing
    implements Instrumenter.ForSingleType {

  public DispatcherServletInstrumentation() {
    super("spring-web");
  }

  @Override
  public String instrumentedType() {
    return "org.springframework.web.servlet.DispatcherServlet";
  }

  @Override
  public String[] helperClassNames() {
    return new String[] {
      packageName + ".SpringWebHttpServerDecorator",
      packageName + ".ServletRequestURIAdapter",
      packageName + ".HandlerMappingResourceNameFilter",
      packageName + ".PathMatchingHttpServletRequestWrapper",
      packageName + ".DataDogHttpServletResponseWrapper",
      //packageName + ".DataDogHttpServletResponseWrapper$WrapperOutputStream"
      packageName + ".DataDogHttpServletResponseWrapper$CustomServletOutputStream",
      packageName+".ContentCachingResponseWrapper",
        packageName+".ContentCachingResponseWrapper$ResponseServletOutputStream",
      packageName+".ContentCachingResponseWrapper$ResponsePrintWriter",
        packageName+".DatadogByteArrayOutputStream",
    };
  }
...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant