I can't find a way to replicate the issue each time. In fact this issue occur rarely, but once occur the code never return.
I can do below modification for replicate Aspose call HashMap.put concurrently with one instance.
I use JDK1.6.0_30 and cells-cells-8.7.0, I change HashMap.java, add some code in put(This modification only let Eclipse can add breakpoint at special line):
//HashMap.java
public V put(K key, V value) {
//Code add here
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if (stackTrace.length > 2 && stackTrace[2].getClassName().contains("zafp"))
System.out.println();
//Code add end
//Original source code
if (key == null)
return putForNullKey(value);
...
//End HashMap.java
//Test Code
for (int z = 0; z < 2; z++) {
final int zz = z;
new Thread() {
public void run() {
Workbook wb = new Workbook();
Worksheet worksheet = wb.getWorksheets().get(0);
Cells cells = worksheet.getCells();
for (int x = 0; x < 10; x++) {
for (int y = 0; y < 10; y++) {
Cell cell = cells.get(x, y);
cell.setValue("" + Math.random() * Math.PI * x / y * zz);
BorderCollection borders = cell.getStyle()
.getBorders();
Border top = borders
.getByBorderType(BorderType.TOP_BORDER);
top.setArgbColor((x << 16) | y | 0xFF000000);
top.setLineStyle(CellBorderType.DASH_DOT);
}
}
try {
wb.save("C:/" + zz + ".html");
} catch (Exception e) {
}
}
}.start();
}
//End Test Code;
Compile HashMap.java with -g option and replace original class file in rt.jar,
Add a breakpoint in HashMap.java ,in line System.out.println,
debug test code in Eclipse
Two thread break on these code System.out.println()
Please note variable "this" is same id of two threads, mean an instance of HashMap change Entry link concurrently!
This is not thread-safe modification!
And if you use this test code, sometimes will make JVM in infinite loop, event all threads done , size of map is wrong , not equals N.
If you change HashMap to ConcurrentHashMap, it work fine.
static Map map = new HashMap();
static int N = 10000;
static CountDownLatch startSignal = new CountDownLatch(1);
static CountDownLatch doneSignal = new CountDownLatch(N);
public static void main(String[] args) {
for (int i = 0; i < N; i++) {
final int j = i;
new Thread(new Runnable(){
public void run() {
try {
startSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(Thread.currentThread().getId()+""+j, "test");
doneSignal.countDown();
}
}).start();
}
startSignal.countDown();
try {
doneSignal.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("done,size:" + map.size());
}