On 2010-09-28 11:15, Wendy Feng (JIRA) wrote:
Synchonrize on mutable field in Permissions.java
------------------------------------------------
Key: HARMONY-6661
URL: https://issues.apache.org/jira/browse/HARMONY-6661
Project: Harmony
Issue Type: Bug
Components: Classlib
Affects Versions: 6.0M1
Environment: Windows XP
Reporter: Wendy Feng
I found a unsafe synchronization in
modules/security/src/main/java/common/java/security/Permissions.java
public final class Permissions extends PermissionCollection implements
Serializable {
...
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
...
klasses = new HashMap();
synchronized (klasses) {
for (Iterator iter = perms.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry) iter.next();
Class key = (Class) entry.getKey();
PermissionCollection pc = (PermissionCollection)
entry.getValue();
if (key != pc.elements().nextElement().getClass()) {
throw new
InvalidObjectException(Messages.getString("security.22")); //$NON-NLS-1$
}
klasses.put(key, pc);
}
}
...
}
...
}
In the above code , a block is synchronized on klasses field. Before the
synchronized block, klasses is assigned to a new value.
Consequence:
Different threads will synchronize on different klasses objects because it has
been assigned to a new value. It breaks the mutual exclusion and update on
klasses would be lost.
I suggest to rewrite it as follow:
public final class Permissions extends PermissionCollection implements
Serializable {
private static final Object monitor = new Object();
...
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
...
klasses = new HashMap();
synchronized (monitor ) {
for (Iterator iter = perms.entrySet().iterator(); iter.hasNext();)
{
Map.Entry entry = (Map.Entry) iter.next();
Class key = (Class) entry.getKey();
PermissionCollection pc = (PermissionCollection)
entry.getValue();
if (key != pc.elements().nextElement().getClass()) {
throw new
InvalidObjectException(Messages.getString("security.22")); //$NON-NLS-1$
}
klasses.put(key, pc);
}
}
...
}
...
}
In this case, readObject play a role like constructor, initialize the object, so
I guess it could be safe here without "synchornized" block. But serialization
may be different, is there any chance that someone could hold a reference to a
incompletely deserialized object and then invoke methods on it?
--
Best Regards,
Regis.