task-23: 图片嵌入成功后立即释放外部缩略图字节副本

BoundedImageCache.release(url) 移除条目并扣减字节计数,byte[] 可被 GC 回收;
embedImage 在 addPicture 成功后立即释放,同一 URL 后续行复用 pictureIndex 不重复嵌入。
全量测试 532 通过。
This commit is contained in:
2026-08-29 18:34:02 +08:00
parent 4a11fd612e
commit 70d724382d
3 changed files with 228 additions and 0 deletions
@@ -246,6 +246,8 @@ public class ShopDataCrawlExcelAssemblyService {
if (pictureIndex == null) {
pictureIndex = workbook.addPicture(image.bytes(), Workbook.PICTURE_TYPE_JPEG);
pictureIndexes.put(normalizedUrl, pictureIndex);
// 嵌入成功后立即释放缩略图字节副本,byte[] 可被 GC 回收;后续行复用 pictureIndex。
imageCache.release(normalizedUrl);
}
Drawing<?> drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = workbook.getCreationHelper().createClientAnchor();
@@ -82,6 +82,21 @@ public class BoundedImageCache extends LinkedHashMap<String, SimilarAsinImageEmb
return put(key, value);
}
/**
* 图片嵌入成功后立即释放缩略图字节副本:移除条目并扣减字节计数,
* 使 byte[] 可被 GC 回收。key 缺失/空白/重复释放均安全返回 null。
*/
public SimilarAsinImageEmbedder.ResizedImage release(String key) {
if (key == null || key.isBlank()) {
return null;
}
SimilarAsinImageEmbedder.ResizedImage removed = super.remove(key);
if (removed != null && removed.bytes() != null) {
sizeBytes -= removed.bytes().length;
}
return removed;
}
private void evictEldest() {
Map.Entry<String, SimilarAsinImageEmbedder.ResizedImage> eldest = entrySet().iterator().next();
sizeBytes -= eldest.getValue().bytes().length;