I got a NullPointerException in my project and I would like to evaluate what is the sevirity of this issue. The exception is thrown just before the thread finished its task and going to die anyway.
My code failed to catch this excepition, so the thread is dead.
Here is a simple simulation of the situation:
public class Test extends Thread {
public static void main(String[] args) throws InterruptedException {
Test thread = new Test();
thread.start();
while(true) {
System.out.println("I'm still here!");
Thread.sleep(1000);
}
}
public void run() {
String s = null;
int len = s.length(); // causes NullPinterException
}
}
My question is: What is going to happened to this poor thread now? Is its linux file descriptor get freed? Is there any stability or memroy issues that may occur in such kind of code?
The handling is not different than with any other terminated thread. The one thing that happens before is the search for an UncaughtExceptionHandler according to the rules (specific Thread, ThreadGroup, all threads) but apart from this the "normal" cleanup procedure follows. There are no specific consequences regarding sytem resources (depending on the Thread implementation) or memory issues when a thread is terminated by an uncaught exception in contrast to a "normal" termination.
This is not about threads at all. Look at your code:
String s = null;
int len = s.length();
When you are calling s.length() the s is indeed null that causes NullPointerException.
Assign some value to s and you will get its length.
Related
I am writing the same code on tutorial. But in tutorial the program never exits, my in my computer it exits after 4 seconds. Why?
tutorial with exact time where this code is shown: https://youtu.be/vzBw1LPupnA?t=169
public class Main {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(() -> {
int i = 0;
while (!stopRequested) {
i++;
System.out.println("i = " + i);
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
The reason that you are seeing different behavior on your machine and in the video is because the program has unspecified behavior. (Or to put it another way, it is not thread-safe.)
You have two threads accessing and updating a shared variable without taking the necessary steps that will guarantee that changes made by one thread are visible to the other. What happens in that case is not specified.
In some cases (e.g. on some platforms) the changes will be visible, either immediately or within a short time.
On others, the changes may never be visible.
In technical terms, there must be a happens-before relationship between the write by on thread and the subsequent read by the other thread. This can be provided by both threads synchronizing on the same mutex or lock, by using a volatile variable, and in other ways. But this code doesn't do any of those things, so there is no guarantee that the state change will be visible.
For more details, read about the Java Memory Model.
The above is sufficient to explain the difference, but there may be a more direct explanation.
In practice, something like a System.out.println can lead to changes in the visibility. Underneath the covers, the println call will typically result in synchronization on the output stream's buffers. That can result in a serendipitous happens-before that is sufficient to guarantee visibility. But this behavior is not specified, so you should not rely on it.
At any rate, adding trace statements can change the behavior of multi-threaded coded. And the fact that you (apparently) added them in your version is a second possible explanation for the difference.
The bottom line here is that a program with a memory visibility flaw is broken, but you may not be able to demonstrate that it is broken.
As the excellent Answer by Stephen C says, your code is not thread-safe.
Establishing an AtomicBoolean early on addresses the visibility problem explained in that other Answer. This class is a thread-safe wrapper around its payload boolean value.
The volatile keyword is another solution. But I find the Atomic… classes simpler and more obvious.
Also, in modern Java we rarely need to address the Thread class directly. Instead, use the Executors framework. Define your task as a Runnable or Callable, and submit to an executor service.
Something like this untested code.
public class Main {
private static final AtomicBoolean stopRequested = new AtomicBoolean( false ) ;
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
int i = 0;
while ( ! stopRequested.get() ) {
i++;
System.out.println("i = " + i);
TimeUnit.MILLISECONDS.sleep(100); // Don’t spin too fast.
}
};
ExecutorService es = Executors.newSingleThreadedExecutorService() ;
es.submit( task ) ;
TimeUnit.SECONDS.sleep(1);
stopRequested.set( true ) ;
TimeUnit.SECONDS.sleep(1);
// Shut down here executor service. Boilerplate taken from Javadoc.
es.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!es.awaitTermination(60, TimeUnit.SECONDS)) {
es.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!es.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Executor service did not terminate");
}
} catch (InterruptedException ex) {
// (Re-)Cancel if current thread also interrupted
es.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
I was trying to intentionally create visibility issues with threads and I got unexpected results:
public class DownloadStatus {
private int totalBytes;
private boolean isDone;
public void increment() {
totalBytes++;
}
public int getTotalBytes() {
return totalBytes;
}
public boolean isDone() {
return isDone;
}
public void done() {
isDone = true;
}
}
public class DownloadFileTask implements Runnable {
DownloadStatus status;
public DownloadFileTask(DownloadStatus status) {
this.status = status;
}
#Override
public void run() {
System.out.println("start download");
for (int i = 0; i < 10_000; i++) { //"download" a 10,000 bytes file each time you run
status.increment(); //each byte downloaded - update the status
}
System.out.println("download ended with: " + status.getTotalBytes()); //**NOTE THIS LINE**
status.done();
}
}
//creating threads, one to download, another to wait for the download to be done.
public static void main(String[] args) {
DownloadStatus status = new DownloadStatus();
Thread t1 = new Thread(new DownloadFileTask(status));
Thread t2 = new Thread(() -> {
while (!status.isDone()) {}
System.out.println("DONE!!");
});
t1.start();
t2.start();
}
So, running this would create a visibility problem - the second thread wouldn't see the updated value since it had cached it before it got written back by the first thread - this causes an endless (while) loop, the second thread is constantly checking the cached isDone(). (at least that's how I think it works).
The thing I don't get is why this visibility problem stops happening when I comment out the line from the second code block that calls status.getTotalBytes().
From my understanding both threads start by caching the status object as-is, so the second thread should constantly check his cached value (and essentially not see the new value updated by the first thread).
Why is this line calling a method in the status object causing this visibility issue? (and more interestingly - why not calling it fixes it?)
What you call a "visibility problem" is actually a data race.
A single thread sees the effects of its operations in the order they are written. That is if you update a variable and then read it, you'll always see the updated value within that thread.
The effects of a thread's execution may be different when viewed from another thread. This is mainly related to the language and the underlying hardware architecture. The compiler may reorder instructions, delay memory writes while keeping values in registers, or the values may be kept in a cache before written to the main memory. Without an explicit memory barrier, the value in the main memory would not be updated. That's what you call the "visibility problem".
It is likely that there is a memory barrier in System.println. So when you execute that line, all updates up to that point will be committed to the main memory, and the other threads can see it. Note that without explicit synchronization, there is still no guarantee that the other threads will see it, because those threads may re-use the value they got for that variable before. There is nothing in the program that tells the compiler/runtime that the values may be changed by other threads.
This is the race condition between two threads. There is nothing to do with status.getTotalBytes() statement in your code. It is the scheduler that decides which thread will run. It is by chance that you are not getting stuck in the infinit loop after commenting the println statement. The main problem in your code that increment and set status should be atomic operation and replace the definition of run method as below. Secondly increment is also not a atomic operation. You can unpredictable results if there is no proper synchronization.
#Override
public void run() {
System.out.println("start download");
incrementAndSetStatus();
}
public synchronized void incrementAndSetStatus(){
for (int i = 0; i < 100000; i++) { //"download" a 10,000 bytes file each time you run
status.increment(); //each byte downloaded - update the status
}
System.out.println("download ended with: " + status.getTotalBytes()); //**NOTE THIS LINE**
status.done();
}
I'm using scanner to read lines from file and replace some text in each line based on given pattern. This is done inside an API. My program is a multithreaded one. At once, more than one thread can call this particular API.
Following is the line scanner initialization line where the thread crashes:
public static void replaceInFile(Properties replacements, Path targetFile) {
...
Scanner in = new Scanner(targetFile, "UTF-8");
...
}
I'm sure no single file will be accessed by two threads at once. Can anyone hint me in the right direction as to what is happening?
UPDATE:
public Void call() throws Exception {
Iterator it = paths.iterator();
while(it.hasNext()){
try {
String filePath = it.next().toString();
//BuildUtil replacer = new BuildUtil();
BuildUtil.replaceInFile(replacements, Paths.get(filePath));
} catch(Exception e) {
e.printStackTrace();
}
}
This is the call() of the thread. Now I observe that it shows "Frame not available" even before stepping into the BuildUtils's replaceInFile method and sometimes after entering in there..I'm not able to figure out what's wrong.. The main thread is exiting I think but I see nothing strange happening here which should make it exit unexpectedly.
I found it. Actually it was my stupidity. I forgot to wait for the threads to exit and so the main thread exited even before threads could complete. Sorry for bothering!
So now I do :
for (int i = 0; i < threadsUsed; i++) {
pool.take().get();
}
for all the threads and shutdown the executor service in finally block
I have made a method to send an e-mail, and I wanted to try if it was possible to call a method inside the method itself with a timer, to do like a scheduler
public void createExcel(){
int year = Calendar.getInstance().get(Calendar.YEAR);
int num_week = data.getCurrentWeek()-1;
ArrayList<DHDemande> ListeDemandes = d.getDemandesForPaie(num_week, year);
try {
data.createFile(ListeDemandes);
Thread.sleep(20000);
createExcel();
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
But now the method doesn't stop (it was obvious) but even if I refresh Apache and if I change the method. How can I stop it ? because I receive an email every 20 second now
The thing with Treads is that there is now save way to tell it to just stop without memory leaks. You can use thread.stop(), this will kill the thread but it may cause memory problems if your objects are too big.
Quote from java doc:
stop() Deprecated. This method is inherently unsafe. Stopping a
thread with Thread.stop causes it to unlock all of the monitors that
it has locked (as a natural consequence of the unchecked ThreadDeath
exception propagating up the stack). If any of the objects previously
protected by these monitors were in an inconsistent state, the damaged
objects become visible to other threads, potentially resulting in
arbitrary behavior. Many uses of stop should be replaced by code that
simply modifies some variable to indicate that the target thread
should stop running. The target thread should check this variable
regularly, and return from its run method in an orderly fashion if the
variable indicates that it is to stop running. If the target thread
waits for long periods (on a condition variable, for example), the
interrupt method should be used to interrupt the wait. For more
information, see Why are Thread.stop, Thread.suspend and Thread.resume
Deprecated?.
Explore the Thread api and see if you can find anything else that suites your needs.
As Borislav mentioned, stop() is incorrect here, you need to call and handle interrupt().
class Test
{
public static Thread helloWorldLater()
{
Thread t = new Thread(new Runnable(){
#Override public void run()
{
try {
Thread.sleep(200);
System.out.println("Hello World");
}
catch(InterruptedException ex)
{
// clean up here
return;
}
}
});
t.start();
return t;
}
public static void main(String[] args) throws InterruptedException
{
Thread t = helloWorldLater();
Thread.sleep(100);
t.interrupt();
// no "Hello World" to be seen
}
}
Alternatively, depending on your Java version, you can also use the more modern concurrency Java APIs.
Besides Borislavs and Konrads legitimate comments on thread.stop(), you are calling the createExcel() method recursively (after Thread.sleep(20000)), so obviously your method will run forever. If you remove that call it should work like you expect it.
A simple scenario:
private static final ExecutorService executor =
Executors.newCachedThreadPool();
public static void main(String... args) throws InterruptedException, ExecutionException {
Future<byte[]> f = null;
for (int i = 0; i < 10; i++) {
f = executor.submit(new Callable<byte[]>(){
#Override
public byte[] call() {
System.out.println("Starting task.");
try {
return new byte[1500 * 1024 * 1024]; // 1500 mb
}
finally {
System.out.println("Task complete.");
}
}
});
}
// System.out.println(f.get().length);
}
When I run the above code it (allegedly) runs without error.
(Strangely, an OutOfMemoryError is being thrown when I profile this code in NetBeans, but not when I run it normally.)
All 10 "Task complete." messages immediatelly show up, in a time-frame far too short for the byte arrays to be actually allocated.
When I uncomment the last line an ExecutionException is thrown.
I know the code example is kind of absurd...
But why is no exception at all being thrown and how can I make the OutOfMemoryError show up? Do I have to catch it? Would that be a safe operation?
You shouldn't catch Errors - they're intended to noisily crash your program. You should only catch an Exception if a. you're logging it / re-throwing it or b. you're handling it; there's no way for you to handle an OutOfMemoryError, so let it crash your program like it's supposed to.
"Task Complete" is showing up when the Future objects have been allocated, not when they're done with their work - you need to call f.get() on each Future to ensure that it's finished allocating its byte array. The program runs slower when you're profiling it, which allows for more Futures to allocate their byte arrays before the Main method terminates, which in turn allows them to use up all of your heap space.
Change f to an ArrayList of futures (and f = executor.submit to f.add(executor.submit)), then iterate through it and call .get() on all of its futures. That should trigger your OutOfMemoryError without using the profiler.
Main thread will not become automatically aware of exceptions throws by threads.
Previous run method was used which doesn't throw exceptions and you were forced to use uncaughtexceptionhandler.
JDK1.5 onwards futures and callables were introduced. Call method of callables throws exception as well as returns a values. Now to catch the exception thrown by call method you need to call future.get().
So your code is working perfectly.