|
18 | 18 | import jadx.core.utils.exceptions.JadxRuntimeException;
|
19 | 19 |
|
20 | 20 | /**
|
21 |
| - * Storage for different attribute types: |
22 |
| - * 1. flags - boolean attribute (set or not) |
23 |
| - * 2. attribute - class instance associated with attribute type. |
| 21 | + * Storage for different attribute types:<br> |
| 22 | + * 1. Flags - boolean attribute (set or not)<br> |
| 23 | + * 2. Attributes - class instance ({@link IJadxAttribute}) associated with an attribute type |
| 24 | + * ({@link IJadxAttrType})<br> |
24 | 25 | */
|
25 | 26 | public class AttributeStorage {
|
26 | 27 |
|
| 28 | + public static AttributeStorage fromList(List<IJadxAttribute> list) { |
| 29 | + AttributeStorage storage = new AttributeStorage(); |
| 30 | + storage.add(list); |
| 31 | + return storage; |
| 32 | + } |
| 33 | + |
27 | 34 | static {
|
28 | 35 | int flagsCount = AFlag.values().length;
|
29 | 36 | if (flagsCount >= 64) {
|
30 | 37 | throw new JadxRuntimeException("Try to reduce flags count to 64 for use one long in EnumSet, now " + flagsCount);
|
31 | 38 | }
|
32 | 39 | }
|
33 | 40 |
|
| 41 | + private static final Map<IJadxAttrType<?>, IJadxAttribute> EMPTY_ATTRIBUTES = Collections.emptyMap(); |
| 42 | + |
34 | 43 | private final Set<AFlag> flags;
|
35 | 44 | private Map<IJadxAttrType<?>, IJadxAttribute> attributes;
|
36 | 45 |
|
37 | 46 | public AttributeStorage() {
|
38 | 47 | flags = EnumSet.noneOf(AFlag.class);
|
39 |
| - attributes = Collections.emptyMap(); |
40 |
| - } |
41 |
| - |
42 |
| - public AttributeStorage(List<IJadxAttribute> attributesList) { |
43 |
| - this(); |
44 |
| - add(attributesList); |
| 48 | + attributes = EMPTY_ATTRIBUTES; |
45 | 49 | }
|
46 | 50 |
|
47 | 51 | public void add(AFlag flag) {
|
@@ -125,21 +129,22 @@ public void remove(IJadxAttribute attr) {
|
125 | 129 | }
|
126 | 130 |
|
127 | 131 | private void writeAttributes(Consumer<Map<IJadxAttrType<?>, IJadxAttribute>> mapConsumer) {
|
128 |
| - if (attributes.isEmpty()) { |
129 |
| - attributes = new IdentityHashMap<>(5); |
130 |
| - } |
131 | 132 | synchronized (this) {
|
| 133 | + if (attributes == EMPTY_ATTRIBUTES) { |
| 134 | + attributes = new IdentityHashMap<>(2); // only 1 or 2 attributes added in most cases |
| 135 | + } |
132 | 136 | mapConsumer.accept(attributes);
|
| 137 | + if (attributes.isEmpty()) { |
| 138 | + attributes = EMPTY_ATTRIBUTES; |
| 139 | + } |
133 | 140 | }
|
134 | 141 | }
|
135 | 142 |
|
136 | 143 | public void unloadAttributes() {
|
137 | 144 | if (attributes.isEmpty()) {
|
138 | 145 | return;
|
139 | 146 | }
|
140 |
| - synchronized (this) { |
141 |
| - attributes.entrySet().removeIf(entry -> !entry.getValue().keepLoaded()); |
142 |
| - } |
| 147 | + writeAttributes(map -> map.entrySet().removeIf(entry -> !entry.getValue().keepLoaded())); |
143 | 148 | }
|
144 | 149 |
|
145 | 150 | public List<String> getAttributeStrings() {
|
|
0 commit comments