Skip to content

Commit 3fbb901

Browse files
committed
Avoid flipping accessible flag in OgnlMemberAccess
Once a field is made accessible, we keep it accessible. Flipping accessible flag causes a race condition. Possibly related to mybatis#1648 .
1 parent 4d7c029 commit 3fbb901

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

src/main/java/org/apache/ibatis/scripting/xmltags/OgnlMemberAccess.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2019 the original author or authors.
2+
* Copyright 2009-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,9 +58,7 @@ public Object setup(Map context, Object target, Member member, String propertyNa
5858
@Override
5959
public void restore(Map context, Object target, Member member, String propertyName,
6060
Object state) {
61-
if (state != null) {
62-
((AccessibleObject) member).setAccessible((Boolean) state);
63-
}
61+
// Flipping accessible flag is not thread safe. See #1648
6462
}
6563

6664
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright 2009-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.apache.ibatis.scripting.xmltags;
18+
19+
import static org.junit.jupiter.api.Assertions.*;
20+
21+
import java.util.ArrayList;
22+
import java.util.HashMap;
23+
import java.util.List;
24+
import java.util.Map;
25+
import java.util.concurrent.ExecutorService;
26+
import java.util.concurrent.Executors;
27+
import java.util.concurrent.Future;
28+
import java.util.stream.IntStream;
29+
30+
import org.junit.jupiter.api.Test;
31+
32+
public class OgnlCacheTest {
33+
@Test
34+
void concurrentAccess() throws Exception {
35+
class DataClass {
36+
@SuppressWarnings("unused")
37+
private int id;
38+
}
39+
int run = 1000;
40+
Map<String, Object> context = new HashMap<>();
41+
List<Future<Object>> futures = new ArrayList<>();
42+
context.put("data", new DataClass());
43+
ExecutorService executor = Executors.newCachedThreadPool();
44+
IntStream.range(0, run).forEach(i -> {
45+
futures.add(executor.submit(() -> {
46+
return OgnlCache.getValue("data.id", context);
47+
}));
48+
});
49+
for (int i = 0; i < run; i++) {
50+
assertNotNull(futures.get(i).get());
51+
}
52+
executor.shutdown();
53+
}
54+
}

0 commit comments

Comments
 (0)