java.lang.NoClassDefFoundError

文章讲述了如何处理Java项目中遇到的NoClassDefFoundError,特别关注ByteArrayBuffer类的缺失问题。作者提供了检查项目依赖、升级或替换依赖、以及创建自定义工具类作为替代方法的详细步骤,并展示了如何将原依赖替换为自定义工具类进行项目测试。
摘要由CSDN通过智能技术生成

错误信息

java.lang.NoClassDefFoundError: com/sun/xml/internal/ws/util/ByteArrayBuffer

复现

经多次尝试,项目内运行正常,编译,打包都没问题,只是在运行Jar包时,出现此错误。

询问ChatGPT

java.lang.NoClassDefFoundError 异常通常表示虚拟机在运行时无法找到类的定义。在你的情况下,异常指出缺少了 com.sun.xml.internal.ws.util.ByteArrayBuffer 类的定义,这是一个 JDK 内部类,不应该直接依赖于它。

解决这个问题的方法如下:

  1. 避免直接依赖 JDK 内部类:尽量避免直接依赖于 JDK 内部类,因为它们不是公共 API 的一部分,可能会导致兼容性问题。

  2. 检查项目依赖:检查你的项目依赖关系,看看是否有引入了直接依赖于 com.sun.xml.internal.ws.util.ByteArrayBuffer 类的库。如果有,尝试找到更好的替代方案。

  3. 升级相关依赖:尝试升级你的项目依赖,特别是涉及到 Web Services 的库。新版本可能已经移除了对这个 JDK 内部类的依赖。

  4. 排除相关依赖:如果确定是某个特定依赖引入了对 com.sun.xml.internal.ws.util.ByteArrayBuffer 的依赖,可以尝试在构建工具(如 Maven 或 Gradle)中排除这个依赖,以避免冲突。

  5. 使用合适的替代方案:尝试寻找替代方案来替代使用 com.sun.xml.internal.ws.util.ByteArrayBuffer 类的功能。可能有其他库或方法可以完成相同的任务。

最重要的是要避免直接依赖于 JDK 内部类,因为它们不是为公共使用而设计的,可能会导致类似的问题。通过遵循最佳实践和避免直接依赖 JDK 内部类,可以帮助确保你的应用程序更具可移植性和稳定性。

地毯式搜寻导入ByteArrayBuffer的类

根据ChatGPT提供的解决方案:

  1. 避免直接依赖 JDK 内部类:发现一个功能类直接导入了此类。
  2. 检查项目依赖:未发现相关依赖
  3. 升级相关依赖:未发现相关依赖
  4. 排除相关依赖:未发现相关依赖
  5. 使用合适的替代方案:开始深入搜寻替代方案!

快速了解 ByteArrayBuffer

源文件如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.sun.xml.internal.ws.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class ByteArrayBuffer extends OutputStream {
    protected byte[] buf;
    private int count;
    private static final int CHUNK_SIZE = 4096;

    public ByteArrayBuffer() {
        this(32);
    }

    public ByteArrayBuffer(int size) {
        if (size <= 0) {
            throw new IllegalArgumentException();
        } else {
            this.buf = new byte[size];
        }
    }

    public ByteArrayBuffer(byte[] data) {
        this(data, data.length);
    }

    public ByteArrayBuffer(byte[] data, int length) {
        this.buf = data;
        this.count = length;
    }

    public final void write(InputStream in) throws IOException {
        while(true) {
            int cap = this.buf.length - this.count;
            int sz = in.read(this.buf, this.count, cap);
            if (sz < 0) {
                return;
            }

            this.count += sz;
            if (cap == sz) {
                this.ensureCapacity(this.buf.length * 2);
            }
        }
    }

    public final void write(int b) {
        int newcount = this.count + 1;
        this.ensureCapacity(newcount);
        this.buf[this.count] = (byte)b;
        this.count = newcount;
    }

    public final void write(byte[] b, int off, int len) {
        int newcount = this.count + len;
        this.ensureCapacity(newcount);
        System.arraycopy(b, off, this.buf, this.count, len);
        this.count = newcount;
    }

    private void ensureCapacity(int newcount) {
        if (newcount > this.buf.length) {
            byte[] newbuf = new byte[Math.max(this.buf.length << 1, newcount)];
            System.arraycopy(this.buf, 0, newbuf, 0, this.count);
            this.buf = newbuf;
        }

    }

    public final void writeTo(OutputStream out) throws IOException {
        int remaining = this.count;

        int chunk;
        for(int off = 0; remaining > 0; off += chunk) {
            chunk = remaining > 4096 ? 4096 : remaining;
            out.write(this.buf, off, chunk);
            remaining -= chunk;
        }

    }

    public final void reset() {
        this.count = 0;
    }

    /** @deprecated */
    public final byte[] toByteArray() {
        byte[] newbuf = new byte[this.count];
        System.arraycopy(this.buf, 0, newbuf, 0, this.count);
        return newbuf;
    }

    public final int size() {
        return this.count;
    }

    public final byte[] getRawData() {
        return this.buf;
    }

    public void close() throws IOException {
    }

    public final InputStream newInputStream() {
        return new ByteArrayInputStream(this.buf, 0, this.count);
    }

    public final InputStream newInputStream(int start, int length) {
        return new ByteArrayInputStream(this.buf, start, length);
    }

    public String toString() {
        return new String(this.buf, 0, this.count);
    }
}

此类是一个单独的实现类,完全可以全选复制代码,自创个工具类粘贴使用,以达成替代方案!

解决方法:使用替代方案

创建工具类ByteArrayBuffer,添加类注释和@Component注解以加入Spring IOC容器。

package com.demo.example.utils;

import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 日期:2024/3/15
 * 该类来源为:com.sun.xml.internal.ws.util.ByteArrayBuffer;
 * 声明:导入此包的类为(xx类)
 * 导入此Java内部类包会导致成功打jar包后,运行jar包出现如下错误:
 * java.lang.NoClassDefFoundError: com/sun/xml/internal/ws/util/ByteArrayBuffer
 * 解决方法:采用替代方案
 * 为了避免直接使用Java内部类,深入此类了解后,决定把此类单独抽取出来,作为一个工具类。
 * 由于此类为官方内部类,所以只写类注释,类内的属性和方法就不再注释处理。
 */
@Component
public class ByteArrayBuffer extends OutputStream {
    protected byte[] buf;
    private int count;
    private static final int CHUNK_SIZE = 4096;

    public ByteArrayBuffer() {
        this(32);
    }

    public ByteArrayBuffer(int size) {
        if (size <= 0) {
            throw new IllegalArgumentException();
        } else {
            this.buf = new byte[size];
        }
    }

    public ByteArrayBuffer(byte[] data) {
        this(data, data.length);
    }

    public ByteArrayBuffer(byte[] data, int length) {
        this.buf = data;
        this.count = length;
    }

    public final void write(InputStream in) throws IOException {
        while(true) {
            int cap = this.buf.length - this.count;
            int sz = in.read(this.buf, this.count, cap);
            if (sz < 0) {
                return;
            }

            this.count += sz;
            if (cap == sz) {
                this.ensureCapacity(this.buf.length * 2);
            }
        }
    }

    public final void write(int b) {
        int newcount = this.count + 1;
        this.ensureCapacity(newcount);
        this.buf[this.count] = (byte)b;
        this.count = newcount;
    }

    public final void write(byte[] b, int off, int len) {
        int newcount = this.count + len;
        this.ensureCapacity(newcount);
        System.arraycopy(b, off, this.buf, this.count, len);
        this.count = newcount;
    }

    private void ensureCapacity(int newcount) {
        if (newcount > this.buf.length) {
            byte[] newbuf = new byte[Math.max(this.buf.length << 1, newcount)];
            System.arraycopy(this.buf, 0, newbuf, 0, this.count);
            this.buf = newbuf;
        }

    }

    public final void writeTo(OutputStream out) throws IOException {
        int remaining = this.count;

        int chunk;
        for(int off = 0; remaining > 0; off += chunk) {
            chunk = remaining > 4096 ? 4096 : remaining;
            out.write(this.buf, off, chunk);
            remaining -= chunk;
        }

    }

    public final void reset() {
        this.count = 0;
    }

    /** @deprecated */
    public final byte[] toByteArray() {
        byte[] newbuf = new byte[this.count];
        System.arraycopy(this.buf, 0, newbuf, 0, this.count);
        return newbuf;
    }

    public final int size() {
        return this.count;
    }

    public final byte[] getRawData() {
        return this.buf;
    }

    public void close() throws IOException {
    }

    public final InputStream newInputStream() {
        return new ByteArrayInputStream(this.buf, 0, this.count);
    }

    public final InputStream newInputStream(int start, int length) {
        return new ByteArrayInputStream(this.buf, start, length);
    }

    public String toString() {
        return new String(this.buf, 0, this.count);
    }
}

原功能类导入信息替换为导入此工具类
相关代码:

// 替换前
import com.sun.xml.internal.ws.util.ByteArrayBuffer;
// 替换后
import com.demo.example.utils.ByteArrayBuffer;

项目测试

测试内容测试结果
能否成功编译、打包
能否成功运行Jar
涉及的原有功能是否可用可用

成功解决!


以上为个人实践总结,如有更好的方法或者有需要改进的地方,欢迎评论区指正。

如果觉得有帮助的话,不妨点个赞和收藏,加个关注吧!

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值