使用thrift,每隔一段时间就会报错:java.lang.OutOfMemoryError: Direct buffer memory

背景:使用thrif(版本0.9.3)对外提供服务,每隔一段时间thrif服务就挂掉。

问题定位过程

1、查看日志,发现存在java.lang.OutOfMemoryError: Direct buffer memory异常,因为thrif用到nio,发现启动服务没有配置直接内存,想当然认为是直接内存过小,于是在jvm启动参数加大了直接内存的最大值(-XX:MaxDirectMemorySize),后续观察。过了一段时间,问题还是复现了。

2、再查日志还是报直接内存溢出,然后再仔细查看日志,发现直接内存溢出时,thrif尝试去解析一个(1个G多)字节数组,为什么会有这么大的对象,thrif都是用定义好的可序列话的对象,后发现向thrif监听的端口发送http请求(直接在浏览器地址栏输入http://ip:port/),就会复现解析大的字节数组,原来thrif用的是可序列话定义好的对象,而发送http请求的话,thrif无法解析http报文,解析出错造成直接内存区生成一个很大的字节数组,造成直接内存溢出。

解决:

1、直接修改thrift源码,设置单个请求报文最大值(修改AbstractNonblockingServer类的MAX_READ_BUFFER_BYTES属性,这个属性是long类型的最大值,相当于1045576TB,这等于没有限制),根据自己的业务场景来修改最大值。

2、也可以升级thrif的版本,高版本已解决这个问题(例:0.12.0 )。

验证:

再次向thrif服务发送http请求,该异常会被程序catch掉,提示

ERROR:Read a frame size of 1295726556, which is bigger than the maximum allowable buffer size for ALL connections.。

不会耗尽直接内存而造成内存溢出了。

<think> 首先,用户在询问关于Java中解决ClassNotFoundException: org.apache.thrift.TEnum错误的方法。我需要根据提供的引用和系统指令来构建回答。 回顾引用: - 引用[1]:讨论java.lang.NoClassDefFoundError: org/apache/thrift/TException,指出缺少thrift jar包,建议添加依赖如<dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.9.3</version> </dependency>。 - 引用[2]:关于ClassNotFoundException: org.apache.struts.action.ForwardAction。 - 引用[3]:关于ClassNotFoundException: org.apache.http.client.HttpClient的解决方式。 - 引用[4]:关于ClassNotFoundException: org.apache.cxf.transport.servlet.CXFServlet,提到缺少cxf jar包。 用户的问题是关于ClassNotFoundException: org.apache.thrift.TEnum。这与引用[1]中的TException相似,但TEnum是另一个类。org.apache.thrift.TEnum是Thrift中的一个接口,用于枚举类型。 系统指令: - 回答必须使用中文。 - 结构清晰,帮助用户逐步解决问题。 - 引用末尾添加引用标识如[^1],自然地添加。 - 生成相关问题。 - 对于数学内容,使用$...$或$$...$$,但这里没有数学内容,所以不需要。 关键点: - ClassNotFoundException表示类路径中缺少所需的类。 - 针对org.apache.thrift.TEnum,它应该来自Apache Thrift库。 - 解决方案类似于引用[1],需要添加Thrift依赖或确保jar包在类路径中。 步骤构建回答: 1. **理解错误**:解释ClassNotFoundException的含义。 2. **原因分析**:指出缺少Thrift库中的TEnum类。 3. **解决方案**: - 添加Apache Thrift依赖到项目中。 - 指定合适的版本。 - 确保依赖管理工具如Maven或Gradle正确配置。 - 检查类路径是否包含Thrift jar。 - 参考引用[1],因为它涉及Thrift相关的错误。 4. **具体建议**:建议添加依赖项,类似于引用[1],但针对TEnum。 5. **额外提示**:确认版本兼容性,因为TEnum可能在特定版本中可用。 6. **引用添加**:自然地添加引用标识,例如参考引用[1]。 7. **生成相关问题**:在回答后添加相关问题部分。 完整回答结构: - 开头:复述问题以示理解。 - 解释错误。 - 给出解决方案步骤。 - 添加引用。 - 结束:相关问题。 解决方案细节: - 依赖:org.apache.thrift:libthrift,因为TEnum是Thrift库的一部分。 - 版本:用户指定了TEnum,所以需要包含这个类的版本。例如,Thrift 0.9.0及以上版本包含TEnum接口(我需要确认这一点,但基于知识,Thrift确实有TEnum)。 - 类似引用[1],建议Maven依赖: <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.13.0</version> <!-- 使用较新或兼容版本 --> </dependency> - 如果使用其他工具,如Gradle,则相应调整。 相关问题生成: - 基于用户查询,生成类似系统指令中的相关问题。 - 例如: 1. 如何验证Thrift依赖是否已正确添加到项目中? 2. ClassNotFoundException的其他常见原因和解决方法? 3. Apache Thrift在不同Java环境中的配置注意事项? 确保回答真实可靠:基于常见Java开发实践和引用内容。 </think> ### 解决 Java 中 ClassNotFoundException: org.apache.thrift.TEnum 错误的方法 `ClassNotFoundException: org.apache.thrift.TEnum` 错误表示 Java 运行时在类路径(Classpath)中找不到 `org.apache.thrift.TEnum` 类。这通常发生在使用 Apache Thrift 库时,项目中缺少必要的 Thrift 依赖项或版本不兼容。`TEnum` 是 Thrift 中用于枚举类型的接口类(如定义序列化协议),如果未正确引入相关 JAR 包,就会触发此错误[^1]。以下是逐步解决方案: #### 1. **添加 Apache Thrift 依赖** - **核心原因**:`org.apache.thrift.TEnum` 属于 Apache Thrift 库,项目中缺少 `libthrift` JAR 包或版本过低会导致类加载失败。 - **解决方案**:通过 Maven 或 Gradle 添加 Thrift 依赖。推荐使用较新版本(如 `0.13.0` 或更高),因为 `TEnum` 在 Thrift 0.8.0 及以上版本中稳定支持。 - **Maven 依赖**(添加到 `pom.xml`): ```xml <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.13.0</version> <!-- 或兼容版本如 0.14.0 --> </dependency> ``` - **Gradle 依赖**(添加到 `build.gradle`): ```groovy implementation 'org.apache.thrift:libthrift:0.13.0' ``` - **验证**:添加后,清理并重建项目(运行 `mvn clean install` 或 `gradle build`),确保依赖下载无误。 #### 2. **检查依赖冲突和版本兼容性** - **问题分析**:如果已添加 Thrift 依赖但仍报错,可能是版本冲突(例如,其他库依赖了旧版 Thrift)或依赖作用域(Scope)设置错误。 - **解决方案**: - 使用 Maven 检查依赖树: ```bash mvn dependency:tree | grep 'org.apache.thrift' ``` 确保输出中只包含一个统一版本(如 `0.13.0`)。若有冲突,在 `pom.xml` 中显式排除旧版本: ```xml <dependency> <groupId>com.other.library</groupId> <artifactId>example</artifactId> <version>1.0</version> <exclusions> <exclusion> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> </exclusion> </exclusions> </dependency> ``` - 确认依赖作用域:确保 `libthrift` 的作用域不是 `provided`(除非在运行时环境已提供)。推荐使用默认作用域(`compile`)。 #### 3. **手动添加 JAR 包(非 Maven/Gradle 项目)** - **适用于**:老式项目或未使用构建工具的情况。 - **步骤**: - 从 [Apache Thrift 官网](https://thrift.apache.org/) 下载包含 `TEnum` 的 JAR 包(如 `libthrift-0.13.0.jar`)。 - 将 JAR 文件添加到项目的类路径: - IDEA/Eclipse:右键项目 → Build Path → Add External Archives。 - 命令行:运行 Java 时指定路径,例如: ```bash java -cp ".:/path/to/libthrift-0.13.0.jar" YourMainClass ``` #### 4. **验证和测试** - 运行简单测试代码检查类是否可加载: ```java public class TestTEnum { public static void main(String[] args) { try { Class.forName("org.apache.thrift.TEnum"); System.out.println("TEnum class found!"); } catch (ClassNotFoundException e) { System.out.println("Error: " + e.getMessage()); } } } ``` - 如果输出 "TEnum class found!",表示问题已解决。 #### 附加提示 - **引用参考**:此错误与 `java.lang.NoClassDefFoundError: org/apache/thrift/TException` 类似,都是因 Thrift 依赖缺失引起[^1]。确保整个 Thrift 组件完整下载,避免部分依赖遗漏。 - **常见陷阱**:Hive 或其他大数据组件可能自带 Thrift JAR,但若组件未完整部署(如部分文件丢失),会触发此类错误。检查 Hive 安装目录的 `lib` 文件夹是否包含 `libthrift-*.jar`。 - **调试工具**:使用 `-verbose:class` 参数运行 Java,查看类加载日志: ```bash java -verbose:class YourMainClass | grep 'org.apache.thrift.TEnum' ``` 通过以上步骤,大多数 `ClassNotFoundException: org.apache.thrift.TEnum` 错误都可解决。如果问题持续,检查项目是否使用了其他冲突库(如 HTTP Client 或 CXF),这些也可能间接导致类加载问题[^2][^3][^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值