Skip to content
This repository was archived by the owner on Sep 4, 2025. It is now read-only.

Commit 5fa867b

Browse files
authored
Merge pull request #2965 from alibaba/bugfix
Bugfix
2 parents 526629f + 4514b55 commit 5fa867b

File tree

93 files changed

+736
-135
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+736
-135
lines changed

.github/ISSUE_TEMPLATE/bug.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ assignees: zhuangjiaju
1616
这里写代码
1717
```
1818
# 提示的异常或者没有达到的效果
19+
大家尽量把问题一次性描述清楚,然后贴上全部异常,这样方便把问题一次性解决掉。
20+
至少大家要符合一个原则就是,能让其他人复现出这个问题,如果无法复现,肯定无法解决。

.github/ISSUE_TEMPLATE/question.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ assignees: ''
1515
```
1616
# 异常提示
1717
大家尽量把问题一次性描述清楚,然后贴上全部异常,这样方便把问题一次性解决掉。
18+
至少大家要符合一个原则就是,能让其他人复现出这个问题,如果无法复现,肯定无法解决。
1819
# 问题描述

.github/workflows/sync2gitee.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 通过 Github action, 在仓库的每一次 commit 后自动同步到 Gitee 上
22
name: Mirror the Github organization repos to Gitee
3-
on: [push, pull_request]
3+
on: [push]
44

55
jobs:
66
repo-sync:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析
1515
* github地址:[https://github.com/alibaba/easyexcel](https://github.com/alibaba/easyexcel)
1616
* gitee地址:[https://gitee.com/easyexcel/easyexcel](https://gitee.com/easyexcel/easyexcel)
1717

18-
# 64M内存20秒读取75M(46W行25列)的Excel(3.0.2+版本)
18+
# 16M内存23秒读取75M(46W行25列)的Excel(3.2.1+版本)
1919

2020
当然还有[极速模式](https://easyexcel.opensource.alibaba.com/qa/read#%E5%BC%80%E5%90%AF%E6%80%A5%E9%80%9F%E6%A8%A1%E5%BC%8F)
2121
能更快,但是内存占用会在100M多一点
@@ -28,7 +28,7 @@ easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析
2828
<dependency>
2929
<groupId>com.alibaba</groupId>
3030
<artifactId>easyexcel</artifactId>
31-
<version>3.2.0</version>
31+
<version>3.2.1</version>
3232
</dependency>
3333
```
3434

easyexcel-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
55
<modelVersion>4.0.0</modelVersion>
6-
76
<parent>
87
<groupId>com.alibaba</groupId>
98
<artifactId>easyexcel-parent</artifactId>
109
<version>${revision}</version>
1110
<relativePath>../pom.xml</relativePath>
1211
</parent>
1312

13+
<url>https://github.com/alibaba/easyexcel</url>
1414
<packaging>jar</packaging>
1515
<artifactId>easyexcel-core</artifactId>
1616
<name>easyexcel-core</name>

easyexcel-core/src/main/java/com/alibaba/excel/ExcelReader.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111
import com.alibaba.excel.read.metadata.ReadSheet;
1212
import com.alibaba.excel.read.metadata.ReadWorkbook;
1313

14+
import lombok.extern.slf4j.Slf4j;
15+
1416
/**
1517
* Excel readers are all read in event mode.
1618
*
1719
* @author jipengfei
1820
*/
21+
@Slf4j
1922
public class ExcelReader implements Closeable {
2023

2124
/**
@@ -104,4 +107,17 @@ public void finish() {
104107
public void close() {
105108
finish();
106109
}
110+
111+
/**
112+
* Prevents calls to {@link #finish} from freeing the cache
113+
*
114+
*/
115+
@Override
116+
protected void finalize() {
117+
try {
118+
finish();
119+
} catch (Throwable e) {
120+
log.warn("Destroy object failed", e);
121+
}
122+
}
107123
}

easyexcel-core/src/main/java/com/alibaba/excel/ExcelWriter.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import com.alibaba.excel.write.metadata.WriteWorkbook;
1313
import com.alibaba.excel.write.metadata.fill.FillConfig;
1414

15+
import lombok.extern.slf4j.Slf4j;
16+
1517
/**
1618
* Excel Writer This tool is used to write value out to Excel via POI. This object can perform the following two
1719
* functions.
@@ -23,6 +25,7 @@
2325
*
2426
* @author jipengfei
2527
*/
28+
@Slf4j
2629
public class ExcelWriter implements Closeable {
2730

2831
private final ExcelBuilder excelBuilder;
@@ -154,4 +157,16 @@ public WriteContext writeContext() {
154157
public void close() {
155158
finish();
156159
}
160+
161+
/**
162+
* Prevents calls to {@link #finish} from freeing the cache
163+
*/
164+
@Override
165+
protected void finalize() {
166+
try {
167+
finish();
168+
} catch (Throwable e) {
169+
log.warn("Destroy object failed", e);
170+
}
171+
}
157172
}

easyexcel-core/src/main/java/com/alibaba/excel/analysis/v03/handlers/BoundSheetRecordHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ public class BoundSheetRecordHandler extends AbstractXlsRecordHandler implements
1616
@Override
1717
public void processRecord(XlsReadContext xlsReadContext, Record record) {
1818
BoundSheetRecord bsr = (BoundSheetRecord)record;
19-
xlsReadContext.xlsReadWorkbookHolder().getBoundSheetRecordList().add((BoundSheetRecord)record);
19+
xlsReadContext.xlsReadWorkbookHolder().getBoundSheetRecordList().add(bsr);
2020
}
2121
}

easyexcel-core/src/main/java/com/alibaba/excel/cache/Ehcache.java

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.File;
44
import java.util.ArrayList;
5+
import java.util.Optional;
56
import java.util.UUID;
67

78
import com.alibaba.excel.context.AnalysisContext;
@@ -15,6 +16,7 @@
1516
import org.ehcache.config.builders.CacheConfigurationBuilder;
1617
import org.ehcache.config.builders.CacheManagerBuilder;
1718
import org.ehcache.config.builders.ResourcePoolsBuilder;
19+
import org.ehcache.config.units.EntryUnit;
1820
import org.ehcache.config.units.MemoryUnit;
1921

2022
/**
@@ -35,6 +37,8 @@ public class Ehcache implements ReadCache {
3537
private static final CacheManager FILE_CACHE_MANAGER;
3638
private static final CacheConfiguration<Integer, ArrayList> FILE_CACHE_CONFIGURATION;
3739
private static final CacheManager ACTIVE_CACHE_MANAGER;
40+
private static final File CACHE_PATH_FILE;
41+
3842
private final CacheConfiguration<Integer, ArrayList> activeCacheConfiguration;
3943
/**
4044
* Bulk storage data
@@ -50,29 +54,61 @@ public class Ehcache implements ReadCache {
5054
*/
5155
private int cacheMiss = 0;
5256

53-
public Ehcache(int maxCacheActivateSize) {
54-
activeCacheConfiguration = CacheConfigurationBuilder
55-
.newCacheConfigurationBuilder(Integer.class, ArrayList.class,
56-
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(maxCacheActivateSize, MemoryUnit.MB))
57-
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(maxCacheActivateSize, MemoryUnit.MB)
58-
.build();
57+
@Deprecated
58+
public Ehcache(Integer maxCacheActivateSize) {
59+
this(maxCacheActivateSize, null);
60+
}
61+
62+
public Ehcache(Integer maxCacheActivateSize, Integer maxCacheActivateBatchCount) {
63+
// In order to be compatible with the code
64+
// If the user set up `maxCacheActivateSize`, then continue using it
65+
if (maxCacheActivateSize != null) {
66+
this.activeCacheConfiguration = CacheConfigurationBuilder
67+
.newCacheConfigurationBuilder(Integer.class, ArrayList.class,
68+
ResourcePoolsBuilder.newResourcePoolsBuilder()
69+
.heap(maxCacheActivateSize, MemoryUnit.MB))
70+
.build();
71+
} else {
72+
this.activeCacheConfiguration = CacheConfigurationBuilder
73+
.newCacheConfigurationBuilder(Integer.class, ArrayList.class,
74+
ResourcePoolsBuilder.newResourcePoolsBuilder()
75+
.heap(maxCacheActivateBatchCount, EntryUnit.ENTRIES))
76+
.build();
77+
}
5978
}
6079

6180
static {
62-
File cacheFile = FileUtils.createCacheTmpFile();
81+
CACHE_PATH_FILE = FileUtils.createCacheTmpFile();
6382
FILE_CACHE_MANAGER =
64-
CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(cacheFile)).build(true);
83+
CacheManagerBuilder.newCacheManagerBuilder().with(CacheManagerBuilder.persistence(CACHE_PATH_FILE)).build(
84+
true);
6585
ACTIVE_CACHE_MANAGER = CacheManagerBuilder.newCacheManagerBuilder().build(true);
6686
FILE_CACHE_CONFIGURATION = CacheConfigurationBuilder
67-
.newCacheConfigurationBuilder(Integer.class, ArrayList.class,
68-
ResourcePoolsBuilder.newResourcePoolsBuilder().disk(10, MemoryUnit.GB))
69-
.withSizeOfMaxObjectGraph(1000 * 1000L).withSizeOfMaxObjectSize(10, MemoryUnit.GB).build();
87+
.newCacheConfigurationBuilder(Integer.class, ArrayList.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
88+
.disk(20, MemoryUnit.GB)).build();
7089
}
7190

7291
@Override
7392
public void init(AnalysisContext analysisContext) {
7493
cacheAlias = UUID.randomUUID().toString();
75-
fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
94+
try {
95+
fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
96+
} catch (IllegalStateException e) {
97+
//fix Issue #2693,Temporary files may be deleted if there is no operation for a long time, so they need
98+
// to be recreated.
99+
if (CACHE_PATH_FILE.exists()) {
100+
throw e;
101+
}
102+
synchronized (Ehcache.class) {
103+
if (!CACHE_PATH_FILE.exists()) {
104+
if (log.isDebugEnabled()) {
105+
log.debug("cache file dir is not exist retry create");
106+
}
107+
FileUtils.createDirectory(CACHE_PATH_FILE);
108+
}
109+
}
110+
fileCache = FILE_CACHE_MANAGER.createCache(cacheAlias, FILE_CACHE_CONFIGURATION);
111+
}
76112
activeCache = ACTIVE_CACHE_MANAGER.createCache(cacheAlias, activeCacheConfiguration);
77113
}
78114

easyexcel-core/src/main/java/com/alibaba/excel/cache/selector/SimpleReadCacheSelector.java

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
import java.io.IOException;
44

5+
import lombok.Data;
6+
import lombok.EqualsAndHashCode;
7+
import lombok.Getter;
8+
import lombok.Setter;
59
import org.apache.poi.openxml4j.opc.PackagePart;
610
import org.slf4j.Logger;
711
import org.slf4j.LoggerFactory;
@@ -15,6 +19,9 @@
1519
*
1620
* @author Jiaju Zhuang
1721
**/
22+
@Getter
23+
@Setter
24+
@EqualsAndHashCode
1825
public class SimpleReadCacheSelector implements ReadCacheSelector {
1926
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleReadCacheSelector.class);
2027
/**
@@ -24,37 +31,46 @@ public class SimpleReadCacheSelector implements ReadCacheSelector {
2431
/**
2532
* If it's less than 5M, use map cache, or use ehcache.unit MB.
2633
*/
27-
private static final int DEFAULT_MAX_USE_MAP_CACHE_SIZE = 5;
34+
private static final long DEFAULT_MAX_USE_MAP_CACHE_SIZE = 5;
35+
2836
/**
29-
* Maximum size of cache activation.unit MB.
37+
* Maximum batch of `SharedStrings` stored in memory.
38+
* The batch size is 100.{@link Ehcache#BATCH_COUNT}
3039
*/
31-
private static final int DEFAULT_MAX_EHCACHE_ACTIVATE_SIZE = 20;
40+
private static final int DEFAULT_MAX_EHCACHE_ACTIVATE_BATCH_COUNT = 20;
3241

3342
/**
3443
* Shared strings exceeding this value will use {@link Ehcache},or use {@link MapCache}.unit MB.
3544
*/
36-
private final long maxUseMapCacheSize;
45+
private Long maxUseMapCacheSize;
3746

3847
/**
3948
* Maximum size of cache activation.unit MB.
49+
*
50+
* @deprecated Please use maxCacheActivateBatchCount to control the size of the occupied memory
51+
*/
52+
@Deprecated
53+
private Integer maxCacheActivateSize;
54+
55+
/**
56+
* Maximum batch of `SharedStrings` stored in memory.
57+
* The batch size is 100.{@link Ehcache#BATCH_COUNT}
4058
*/
41-
private final int maxCacheActivateSize;
59+
private Integer maxCacheActivateBatchCount;
4260

4361
public SimpleReadCacheSelector() {
44-
this(DEFAULT_MAX_USE_MAP_CACHE_SIZE, DEFAULT_MAX_EHCACHE_ACTIVATE_SIZE);
4562
}
4663

47-
public SimpleReadCacheSelector(long maxUseMapCacheSize, int maxCacheActivateSize) {
48-
if (maxUseMapCacheSize <= 0) {
49-
this.maxUseMapCacheSize = DEFAULT_MAX_USE_MAP_CACHE_SIZE;
50-
} else {
51-
this.maxUseMapCacheSize = maxUseMapCacheSize;
52-
}
53-
if (maxCacheActivateSize <= 0) {
54-
this.maxCacheActivateSize = DEFAULT_MAX_EHCACHE_ACTIVATE_SIZE;
55-
} else {
56-
this.maxCacheActivateSize = maxCacheActivateSize;
57-
}
64+
/**
65+
* Parameter maxCacheActivateSize has already been abandoned
66+
*
67+
* @param maxUseMapCacheSize
68+
* @param maxCacheActivateSize
69+
*/
70+
@Deprecated
71+
public SimpleReadCacheSelector(Long maxUseMapCacheSize, Integer maxCacheActivateSize) {
72+
this.maxUseMapCacheSize = maxUseMapCacheSize;
73+
this.maxCacheActivateSize = maxCacheActivateSize;
5874
}
5975

6076
@Override
@@ -68,6 +84,9 @@ public ReadCache readCache(PackagePart sharedStringsTablePackagePart) {
6884
return new MapCache();
6985
}
7086
}
87+
if (maxUseMapCacheSize == null) {
88+
maxUseMapCacheSize = DEFAULT_MAX_USE_MAP_CACHE_SIZE;
89+
}
7190
if (size < maxUseMapCacheSize * B2M) {
7291
if (LOGGER.isDebugEnabled()) {
7392
LOGGER.debug("Use map cache.size:{}", size);
@@ -77,6 +96,17 @@ public ReadCache readCache(PackagePart sharedStringsTablePackagePart) {
7796
if (LOGGER.isDebugEnabled()) {
7897
LOGGER.debug("Use ehcache.size:{}", size);
7998
}
80-
return new Ehcache(maxCacheActivateSize);
99+
100+
// In order to be compatible with the code
101+
// If the user set up `maxCacheActivateSize`, then continue using it
102+
if (maxCacheActivateSize != null) {
103+
return new Ehcache(maxCacheActivateSize, maxCacheActivateBatchCount);
104+
} else {
105+
if (maxCacheActivateBatchCount == null) {
106+
maxCacheActivateBatchCount = DEFAULT_MAX_EHCACHE_ACTIVATE_BATCH_COUNT;
107+
}
108+
return new Ehcache(maxCacheActivateSize, maxCacheActivateBatchCount);
109+
}
110+
81111
}
82112
}

0 commit comments

Comments
 (0)