验证代码
枚举类型
public enum OrderStatusEnum {
CREATE(1),
COMPLETE(10);
private int status;
OrderStatusEnum(int status) {
this.status = status;
}
private static final OrderStatusEnum[] VALUES = OrderStatusEnum.values();
public static OrderStatusEnum matcher(int value) {
// 方式1
/*for (OrderStatusEnum ele : values()) {
if (ele.status == value) {
return ele;
}
}*/
// 方式2 - 推荐
for (OrderStatusEnum ele : VALUES) {
if (ele.status == value) {
return ele;
}
}
return OrderStatusEnum.CREATE;
}
}
验证代码
public class AnswerEnumApp {
public static void main(String[] args) {
for (int i = 0; i < 100000000; i++) {
OrderStatusEnum orderStatusEnum = OrderStatusEnum.matcher(1);
}
}
}
JVM 启动参数: -Xms100M -Xmx100M -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
结论
使用方式1
进行枚举元素匹配的话, 系统会进行多次的GC, 使用方式2
的话, 系统GC次数是1次
原因
public class AnswerEnumApp {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(OrderStatusEnum.values());
}
}
}
程序运行输出
[Lcom.jaemon.OrderStatusEnum;@531d72ca
[Lcom.jaemon.OrderStatusEnum;@22d8cfe0
[Lcom.jaemon.OrderStatusEnum;@579bb367
[Lcom.jaemon.OrderStatusEnum;@1de0aca6
[Lcom.jaemon.OrderStatusEnum;@255316f2
[Lcom.jaemon.OrderStatusEnum;@41906a77
[Lcom.jaemon.OrderStatusEnum;@4b9af9a9
[Lcom.jaemon.OrderStatusEnum;@5387f9e0
[Lcom.jaemon.OrderStatusEnum;@6e5e91e4
[Lcom.jaemon.OrderStatusEnum;@2cdf8d8a
说明: values() 方法返回的为数组, 每次调用枚举类对应的 values() 方法返回的数组对象都不相同(即: 其在内存中的存储地址不相同)
项目中排查
# 获取服务的PID
jps -lmv
# 保存堆信息
jmap -dump:format=b,file=HeapDump.bin <PID>
# 分析内存中对象情况
jhat -J-mx1024m -stack false -port 7001 HeapDump.bin
# 访问地址, 并根据项目包名或类名搜索相关类在内存中的实例个数
http://localhost:7001/histo/