Java优化 - 领域对象

Domain objects表达程序里的业务概念。比如电子商务系统里的Order、OrderItem和DeliverySchedule。这些类型之间有相关关系(Order可以包含多个OrderItem实例)。例如:

public class Order {
    private final long id;
    private final List<OrderItem> items = new ArrayList<>();
    private DeliverySchedule schedule;

    public Order(long id) {
        this.id = id;
    }

    public DeliverySchedule getSchedule() {
        return schedule;
    }

    public void setSchedule(DeliverySchedule schedule) {
        this.schedule = schedule;
    }

    public List<OrderItem> getItems() {
        return items;
    }

    public long getId() {
        return id;
    }
}

public class OrderItem {
    private final long id;
    private final String description;
    private final double price;

    public OrderItem(long id, String description, double price) {
        this.id = id;
        this.description = description;
        this.price = price;
    }

    @Override
    public String toString() {
        return "OrderItem{" + "id=" + id + ", description=" +
                description + ", price=" + price + '}';
    }
}

public class DeliverySchedule {
    private final LocalDate deliveryDate;
    private final String address;
    private final double deliveryCost;

    private DeliverySchedule(LocalDate deliveryDate, String address,
                             double deliveryCost) {
        this.deliveryDate = deliveryDate;
        this.address = address;
        this.deliveryCost = deliveryCost;
    }

    public static DeliverySchedule of(LocalDate deliveryDate, String address,
                                      double deliveryCost) {
        return new DeliverySchedule(deliveryDate, address, deliveryCost);
    }

    @Override
    public String toString() {
        return "DeliverySchedule{" + "deliveryDate=" + deliveryDate +
                ", address=" + address + ", deliveryCost=" + deliveryCost + '}';
    }
}

可以看到,领域类型之间有所有权关系,见下图。当然,领域对象图的叶子节点,大部分是简单的数据类型,比如字符串、原始类型和LocalDateTime。
Java优化 - 领域对象

使用jmap -histo命令,可以查看堆内状态,当然,也可以使用GUI工具,比如VisualVM。学习这些工具,可以诊断领域对象的内存泄漏情况。
另一个常见的领域对象泄漏行为是“所有代”效应-特定类型的对象没有被回收。这意味着他们会存活足够长时间成为Tenured,经过足够多的survive回收之后,有很大的代计数(generational count)。
如果我们绘制每个代计数的每个数据类型的字节数量的直方图,可以看到泄漏的领域对象跨越所有的代。应该查看领域对象相关的数据集的大小,看这些值是否合理。
而短期存活的领域对象能导致浮动垃圾问题。回想一下并发回收的SATB约束-如果在标记周期开始后分配的对象,无论有多短命,也被认为是活的。领域对象泄漏能导致高的GC标记时间,根本原因是单个长期存活的对象会让整个对象链长期存活。

相关文章:

  • 2021-11-09
  • 2021-12-22
  • 2021-07-23
  • 2022-02-18
  • 2022-12-23
  • 2021-04-11
  • 2018-06-26
猜你喜欢
  • 2022-12-23
  • 2021-06-21
  • 2021-05-15
  • 2021-12-08
  • 2020-01-08
  • 2021-11-15
  • 2022-12-23
相关资源
相似解决方案