Why am i getting ConcurrentModificationException on this unmodifiableSet? - java

I'm getting a java.util.ConcurrentModificationException on the line where the for-loop starts (see comment in code).
Why am i getting ConcurrentModificationException on this unmodifiableSet?
final Set<Port> portSet = Collections.unmodifiableSet(node.getOpenPorts());
if (!portSet.isEmpty()) {
StringBuilder tmpSb = new StringBuilder();
for (Port pp : portSet) { // <------- exception happening here
tmpSb.append(pp.getNum()).append(" ");
}
}
I've never witnessed this, but I'm getting crash reports from Google.

Something must be modifying the underlying set; i.e. the set returned by node.getOpenPorts().
Instead of wrapping the set with an "unmodifiable" wrapper, you could copy it.
final Set<Port> portSet = new HashSet<>(node.getOpenPorts());
But as a commenter (#Slaw) pointed out, that just moves the iteration inside the constructor and you would still get CCMEs.
The only real solutions are:
Change the implementation of the node class to use a concurrent set class for the port list that won't throw CCMEs if the collection is mutated while you are iterating it.
Change the implementation of the node class to return a copy of the port list. Deal with the updates-while-copying race condition with some internal locking.
Put a try / catch around the code and repeat the operation if you get a CCME
I've never witnessed this, but I'm getting crash reports from Google.
Yes. The problem only occurs if this code is executed while the open port list is changing.

Related

How List<> object reference works?

I have List<CapturedImage> capturedImageList = assingedFromSomewhere();
What will happen if I delete element 0 of capturedImageList which is currently being processed by a separate Thread?
// Procesing a Thread
capturedImage.deleteImageFile(capturedImageList.get(0).getAbsolutePath());
if (capturedImage.saveToDisk(bitmap_original)) {
// Note : Thred process in not completed yet
capturedImageList.remove(0);
capturedImageList.add(0, capturedImage);
}
Will the file will get deleted?
If so, how is the object reference is working here?
I haven't tried this but i believe you will encounter a concurrent modification exception,
if you try to manipulate a resource which is already in use.. instead you can use a
CopyOnWriteArrayList

NoSuchElementException even after isEmpty check

Im using a LinkedList in Java and have defined it as:
private final Queue<Collection<String>> data = new LinkedList<Collection<String>>();
The problem occurs when I try accessing it, like shown in this code:
synchronized (data) {
if (data.isEmpty())
{
return;
}
data.remove();
}
This works well under most circumstances. But under some rare unknown scenario it throws the exception
java.util.NoSuchElementException
The exception is thrown at
data.remove();
As per my understanding the above exception is thrown if a remove is tried on the queue that is empty.
But I have already placed a check for isEmpty() before trying remove().
Then why would it throw such an exception?
I've seen a number of similar posts about this but couldn't get a convincing answer. Since I have synchronized on the queue, I just do not understand the cause for this.
Any help is much appreciated.

ConcurrentModificationException crashes my app

My Android app has an IntentService where it requests a list of MessageThreads objects from Facebook, parses the JSON response to build an ArrayList of the objects:
ArrayList<MessageThread> mMessageThreads = new ArrayList<MessageThread>();
Then it calls FB again in the same service, get the names for the MessageThread ids and matches them with the MessageThread objects. At this point I have an ArrayList with complete MessageThread objects and I insert them into an SQLite db.
// save to db and broadcast
for (MessageThread message : mMessageThreads) {
((FBClientApplication)getApplication()).getMessagesData().insertOrIgnore(message.toContentValues();
}
where:
public void insertOrIgnore(ContentValues values) {
SQLiteDatabase db = this.dbHelper.getWritableDatabase();
db.insertWithOnConflict(TABLE, null, values, SQLiteDatabase.CONFLICT_IGNORE);
}
Via ACRA reports I see that intermittently the line
for (MessageThread message : mMessageThreads)
throws an ConcurrentModificationException and the app forcloses. I haven't been able to isolate under what conditions. I read about this Exception and as I understand it it happens when we remove items from an ArrayList while iterating over it, but I'm not removing items from the list. Any pointers to help with this problem are greatly appreciated.
It also happens when you add items to an ArrayList while iterating over it, which it looks like you might do in this code.
In general, it's any "structural modification" that occurs to the ArrayList that can cause a CME while iterating.
What you can try to do is when you iterates your Collection instead of using the original you can make a copy right there, so you will have something like:
for (MessageThread message : new List<MessageThread>(mMessageThreads))
That will help you to avoid CuncurrentModificationException.
Now if you really want to get fancy you can protect your code using synchronized blocks such as:
synchronized(mMessageThreads){
for (MessageThread message : new List<MessageThread>(mMessageThreads)){
...
}
With this last pice of code you will restrict the access to mMessageThreads, if somebody it's using it it will get locked, so if somebody else wants to use it needs to wait until the first one is done.

Deal with concurrent modification on List without having ConcurrentModificationException

I have a stateful EJB which calls an EJB stateless method of Web parsing pages.
Here is my stateful code :
#Override
public void parse() {
while(true) {
if(false == _activeMode) {
break;
}
for(String url : _urls){
if(false == _activeMode) {
break;
}
for(String prioritaryUrl : _prioritaryUrls) {
if(false == _activeMode)
break;
boursoramaStateless.parseUrl(prioritaryUrl);
}
boursoramaStateless.parseUrl(url);
}
}
}
No problem here.
I have some asynchronously call (with JMS) that add to my _urls variable (a List) some value. Goal is to parse new url inside my infinity loop.
I receive ConcurrentModificationException when I try to add new url in my List via JMS onMessage method but it seems to be working because this new url is parsed.
When I try to wrap a synchronized block :
while(true){
synchronized(_url){
// code...
}
}
My new url is never parsed, I expected to be parsed after a for() loop finished...
So my question is : how can I modify List when it's accessed inside a loop without having ConcurrentModificationException please ?
I just want 2 threads to modify some shared resource at same time without synchronized block...
You may want a CopyOnWriteArrayList.
For (String s : urls) uses an Iterator internally. The iterator checks for concurrent modification so that its behavior is well defined.
You can use a for(int i= ... loop. This way, no exception is thrown, and if elements are only added to the end of the List, you still get a consistent snapshot (the list as it exists at some time during the iteration). If the elements in the list are moved around, you may get missing entries.
If you want to use synchronised, you need to synchronise on both ends, but that way you lose concurrent reads.
If you want concurrent access AND consistent snapshots, you can use any of the collections in the java.util.concurrent package.
CopyOnWriteArrayList has already been mentioned. The other interesting are LinkedBlockingQueue and ArrayBlockingQueue (Collections but not Lists) but that's about all.
ok thank you guys.
So I made some modifications.
1) added iterator and leaving synchronized block (inside parse() function and around addUrl() function which add new url to my List)
--> it's work like a charm, no ConcurrentModificationException launched
2) added iterator and removed synchronized blocks
--> ConcurrentModificationException is still launched...
For now, I will read more about your answers and test your solutions.
Thank you again guys
First, forget about synchronized when running into Java EE container. It bothers the container to optimize threads utilization and will not work in clustered environment.
Second, it seems that your design is wrong. You should not update private field of the bean using JMS. This thing causes ConcurrentModificationException. You probably should modify your bean to retrieve the collection from database and your MDB to store the URL into the Database.
Other, easier for you solution is the following.
Retrieve the currently existing URLs and copy them to other collection. Then iterate over this collection. When the global collection is updated via JMS the update is not visible in the copied collection, so no exceptions will be thrown:
while(true) {
for (String url : copyUrls(_prioritaryUrls)) {
// deal with url
}
}
private List<String> copyUrls(List<Stirng> urls) {
return new ArrayList<String>(urls); // this create copy of the source list
}
//........
public void onMessage(Message message) {
_prioritaryUrls.add(((TextMessage)message).getText());
}

NullPointerException on first thread

EDIT:
After making all the changes you suggested, the problem remained. The debugger said the lemma variable was null, but the fixes I applied didn't make things better. So, due to deadline issues, I decided to approach the problem from another view. Thank you all for your help. :)
I am writing a small program and a NullPointerException drives me crazy. I have two classes: SystemDir and Search. The first one is just an encapsulation of initial directory and a search lemma. The Search class is shown below. Briefly, I want one thread to search the first level directory and the other one to expand the subdirectories. That's where I get the exception. The exception string is
Exception in thread "Thread-0" java.lang.NullPointerException
at Search.searchFiles(Search.java:59)
at Search.<init>(Search.java:53)
at SystemDir.<init>(SystemDir.java:61)
at Search$1.run(Search.java:45)
at java.lang.Thread.run(Thread.java:679)
Where the 3 points are t.start() inside the final loop, searchFiles method call, some lines above and the new SystemDir call in the run method. Can you help me please?
public class Search {
private Thread t;
public Search(String[] subFiles, final String[] subDir, final String lemma) {
t = new Thread(new Runnable() {
#Override
public void run() {
for(int i=0;i<subDir.length;i++) {
try {
System.out.println(subDir[i]);
new SystemDir(subDir[i], lemma);
}
catch (NoDirectoryException ex) {
Logger.getLogger(Search.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
});
searchFiles(subFiles,lemma);
}
private void searchFiles(String[] subFiles, String lemma) {
for(int i=0;i<subFiles.length;i++) {
t.start();
if(subFiles[i].contains(lemma)) {
System.out.println(subFiles[i]);
}
}
}
}
As a rule, never start a thread from a constructor. It can create all sorts of issues, which may be responsible for the exception you get.
Create the thread like you do in your constructor, make searchFiles public and call that method from the client code, not from the constructor.
Apart from that, have you checked that:
subFiles is not null
none of the subFiles[i] is null
lemma is not null
(add println statements if necessary)
and as pointed out by #Gray, you can't start a thread more than once.
You have failed to posted the source code for SystemDir, but the stack trace says that its constructor is trying to create a new Search object in addition to the one that created the thread in the first place.
More concretely, probably the new Search(...) expression somewhere in SystemDir's constructor is passing null for subFiles. Is there a call to File.list() somewhere that you haven't checked for a null return from, perhaps? Note that list() returns null if it cannot list a directory at all, due to anything from missing permissions to directory-not-found.
Also, It appears you're attempting to start the same thread object more than once. That will cause an IllegalThreadStateException if there is ever more than one element in subFiles.
You have not included all the code.
With the information provided:
in searchFiles either t, subFiles, or subFiles[i] is null.
Your code itself doesn't make much sense.
That makes it hard to spot the error.
I recommend using the Eclipse debugger, and check WHICH value is null.
As far as I can tell, your problem is within the recursion into SystemDir, where you don't provide the code of.
In your searchFiles method, what is the point of starting the thread in a loop? Do you want to run the thread on each execution of the loop? I think you are missing something here.
Check if some value that you are passing to the constructor is null.

Categories

Resources