如何利用Lombok的@ToString与@EqualsAndHashCode缓解元空间膨胀?
如何通过Lombok的@ToString和@EqualsAndHashCode缓解元空间膨胀?
背景与问题
- 开发的大型应用包含大量用作MyBatis resultType的DTO,对应遗留数据库表,每个DTO含20-100个字段且无法修改表结构。
- 所有DTO使用Lombok的
@Getter、@Setter、@ToString、@EqualsAndHashCode减少样板代码。 - 应用元空间占用过高,排查发现这些DTO占了超半数元空间,而
@ToString和@EqualsAndHashCode生成的代码会随字段数量增加大幅膨胀。
可行的Lombok配置优化方案
1. 排除不必要的字段
如果某些字段不需要参与toString、equals和hashCode计算,可直接排除:
- 对
@ToString使用exclude参数:@ToString(exclude = {"createTime", "updateTime"}) - 对
@EqualsAndHashCode使用exclude参数:@EqualsAndHashCode(exclude = {"version", "serialVersionUID"})
或者用字段级注解更直观地标记排除项:
@Getter @Setter @ToString @EqualsAndHashCode public class LegacyDTO { private Long id; private String name; @ToString.Exclude @EqualsAndHashCode.Exclude private Date createTime; @ToString.Exclude private String internalRemark; }
2. 仅包含必要字段
适合字段多但需要参与逻辑的字段少的场景,明确指定要包含的字段:
@ToString用of参数:@ToString(of = {"id", "name"})@EqualsAndHashCode用of参数:@EqualsAndHashCode(of = {"id"})
也可通过字段级注解标记需要包含的项:
@Getter @Setter @ToString(of = {}) @EqualsAndHashCode(of = {}) public class LegacyDTO { @ToString.Include @EqualsAndHashCode.Include private Long id; @ToString.Include private String name; private Date createTime; private String internalRemark; }
3. 禁用不必要的父类字段参与
默认@EqualsAndHashCode的callSuper为false,如果你的DTO没有继承需要参与计算的父类字段,保持该配置即可,避免生成额外的父类字段处理代码:
@EqualsAndHashCode(callSuper = false) // 显式声明更清晰
4. 简化toString生成的代码
- 使用
doNotUseGetters参数,直接访问字段而非调用getter方法,减少代码复杂度:@ToString(doNotUseGetters = true) - 设
includeFieldNames为false,省略字段名只输出值,缩短生成的方法代码:@ToString(includeFieldNames = false)
5. 移除不必要的注解
如果你的DTO仅用作MyBatis的resultType,业务逻辑中不需要调用toString、equals或hashCode(比如不会放入集合、不会打印日志),可以直接移除@ToString和@EqualsAndHashCode,从根源减少生成的字节码。
额外建议
除了Lombok配置,还可以考虑:
- 拆分超大DTO:如果业务允许,将一个超大DTO拆分为多个小DTO,对应不同查询场景(比如列表查询用精简版,详情查询用完整版),注意不要违反现有表结构限制。
- 调整JVM元空间参数:适当增大
-XX:MetaspaceSize和-XX:MaxMetaspaceSize,但这只是缓解手段,并非根本解决办法。
内容的提问来源于stack exchange,提问作者SATO Yusuke
相关产品推荐
相关产品推荐

