Java Thread and Exception? - java

I'm learning Java threads tutorial and can't understand the explanation of last question 'Threads and exceptions':
Now suppose we run this test:
#Test public void testThreadOops() {
new Thread(() -> { throw new Error("thread oops"); }).start();
}
Is a stack trace for Error: thread oops printed? ( ) Yes ( ) No
The test: ( ) Passes ( ) Fails
The explanation for this question is:
The Error occurs on the newly-created thread, terminating that thread with a stack trace on the console. But the test method testThreadOops returns normally – there is no exception on the main thread – and the JUnit test passes. It does not detect the oops.
Why is there no exception in the main thread?

Is a stack trace for Error: thread oops printed?
It depends.
An uncaught exception on a child thread (i.e. not the "main" thread) will be passed to the thread's uncaught exception handler, the threadgroup uncaught exception handler, or the default uncaught exception handler. These would typically be responsible for printing a stacktrace.
If you (or your framework) don't set a handler, the default behavior is to do nothing, and there won't be a stacktace anywhere.
(The methods for setting handlers are described in the javadocs for Thread.)
Why is there no exception in the main thread?
Because the exception is not thrown on the main thread. It is thrown ... and must be caught / handled ... on the child thread's stack.
Think of it this way. If an exception on a child thread was somehow rethrown on the parent thread, where would you catch it? How would you deal with it? What if it was a checked exception, and the context didn't allow that particular exception to be thrown?

There is no exception thrown in the main thread simply because this code doesn't throw an exception in the main thread. It starts a new thread, and throws an exception in that new thread - not in the main thread.
When an exception is thrown (and not caught) in a thread, that thread terminates, but it doesn't "pass" the exception back to the "parent" thread that started it in the first place. If that happened, any thread which started other threads would continuously be at risk of stopping at any time because of an exception thrown in one of its "child" threads. If the "parent" thread were stopped half-way through some computation, it could leave some data in an invalid state.

In the method below you are throwing an exception in the new thread you create not the main thread of the application. So no exception is thrown in the main thread.
new Thread(() -> { throw new Error("thread oops"); }).start();
Normally when an exception occurs in a thread it terminates itself instead of passing the exception in the main thread. This is to protect the main(parent thread) from stopping incase of child thread cause an exception.

Related

Kotlin process waits for all threads to finish?

I wrote this simple testing program:
fun main() {
println("Main Start")
thread {
println("Thread Start")
Thread.sleep(3000)
println("Thread End")
}
println("Main End")
}
As I can see, the output is:
Main Start
Main End
Thread Start
Thread End
My expectation is that at-least the "Thread End" message will not be printed,
Cause that main function is ended and this main thread should be done running.
Is Kotlin process always waiting for threads to finish before done?
The thread that you have created is a non-daemon thread, and just like in Java, the JVM will not terminate until all the non-daemon thread are finished.
From Kotlin documentation one can read:
fun thread(
start: Boolean = true,
isDaemon: Boolean = false,
contextClassLoader: ClassLoader? = null,
name: String? = null,
priority: Int = -1,
block: () -> Unit ): Thread Creates a thread that runs the specified block of code.
Parameters
start - if true, the thread is immediately started.
isDaemon - if true, the thread is created as a daemon thread. The Java
Virtual Machine exits when the only threads running are all daemon
threads.
contextClassLoader - the class loader to use for loading classes and
resources in this thread.
name - the name of the thread.
priority - the priority of the thread.
Threads in Kotlin, by default, are non-daemon threads. This is why you can still see the output of the thread even thought the main thread have finished its execution. Set the isDaemon to true, and you will see the following output instead:
Main Start
Main End
Thread Start

Synchronous and Asynchronous exceptions in Java

While reading jvm specification I came across exception (2.10 Exceptions)
Most exceptions occur synchronously as a result of an action by the
thread in which they occur. An asynchronous exception, by contrast,
can potentially occur at any point in the execution of a program ...
What are the differences between the two types ?
Keeping reading, the specification gives and example of an asynchronous exception
An asynchronous exception occurred because: – The stop method of class
Thread or ThreadGroup was invoked, or – An internal error occurred in
the Java Virtual Machine implementation.
But what makes stop method of a class thread special in this regard ?
Can you explain the differences between the two and give some examples of them, other than the given ones ?
The stop method can be called from another thread which could leave the data altered by the thread stopped in an inconsistent state.
For this reason Thread.stop() is being removed. I suggest you not use it.
Can you explain the differences between the two and give some examples of them, other than the given ones
The difference is that an asynchronous exception is triggered by another thread at any point in the code.
They should not happen under normal operation.
A specific implementation of the JVM could have other errors but there is not exhaustive list.
There isn't much you can do about except shutdown gracefully.
Here's an example showing the two types of exception. Consider the following code snippets, which show the two kinds of exception being raised, and handled:
public static void main(String[] args) throws Exception {
try {
syncException();
} catch (RuntimeException re) {
System.out.println("-1-");
re.printStackTrace();
}
CompletableFuture<Void> f = null;
try {
f = asyncException();
} catch (RuntimeException ex) {
System.out.println("-2-" + Thread.currentThread().getName());
ex.printStackTrace();
}
try {
f.get();
} catch (Exception ex) {
System.out.println("-3-");
ex.printStackTrace();
}
}
A synchronous exception
private static void syncException() {
throw new RuntimeException("Sync exception #" + Thread.currentThread().getName());
}
And an asynchronous exception - raised in a different thread from the calling code:
private static CompletableFuture<Void> asyncException() {
return CompletableFuture.runAsync(() -> {
throw new RuntimeException("Async exception #" + Thread.currentThread().getName());
}, Executors.newFixedThreadPool(1));
}
Now, when that code is executed, the following stack traces are produced:
The synchronous exception's stack trace:
-1-
java.lang.RuntimeException: Sync exception #main
at stackoverflow.Main.syncException(Main.java:34)
at stackoverflow.Main.main(Main.java:11)
Note that -2- was not printed, because the exception was asynchronous. See the third catch block's stack trace for how asynchronous exceptions are handled. Note that the thread in which the exception was raised is different from the one printing the stack trace:
-3-
java.util.concurrent.ExecutionException: java.lang.RuntimeException: Async exception #pool-1-thread-1
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at stackoverflow.Main.main(Main.java:26)
Caused by: java.lang.RuntimeException: Async exception #pool-1-thread-1
at stackoverflow.Main.lambda$0(Main.java:39)
at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1626)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
An asynchronous exception, by contrast, can potentially occur at any point in the execution of a program ...
Just a comment on this: you'll notice that the code in thread pool-1-thread-1 could raise the exception any time of the main thread's execution. This is probably relative among threads. But in this example, the main thread being the main programe execution, we can say that the "Async exception #pool-1-thread-1" exception occurred asynchronously.

FATAL EXCEPTION: RxCachedThreadScheduler-1 when trigger dispose. Why?

I have the following RxJava 2 code (in Kotlin), which have an Observable that
disposable = Observable.create<String>({
subscriber ->
try {
Thread.sleep(2000)
subscriber.onNext("Test")
subscriber.onComplete()
} catch (exception: Exception) {
subscriber.onError(exception)
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ result -> Log.d("Test", "Completed $result") },
{ error -> Log.e("Test", "Completed ${error.message}") })
While it is still Thread.sleep(2000), I perform disposable?.dispose() call, it will error out
FATAL EXCEPTION: RxCachedThreadScheduler-1
Process: com.elyeproj.rxstate, PID: 10202
java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:371)
at java.lang.Thread.sleep(Thread.java:313)
at presenter.MainPresenter$loadData$1.subscribe(MainPresenter.kt:41)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
I expect the dispose would help to cancel the operation silently, or at most, have the error catch with with the Log.e on the subscribe. However, it just crash as per the error message above.
Why did the Exception escape? Isn't dispose suppose to cancel the entire operation silently without crashing?
There is a combination of factors here:
dispose of a stream that uses subscribeOn also disposes of the thread used. This also involves calling Thread.interrupt() when using Schedulers.io(). This causes the exception in your case.
InterruptedException is an Exception thrown by Thread.sleep, so it is caught by your code and passed to onError like any other exception.
Calling onError after dispose redirects the error to the global error handler due to RxJava2's policy of NEVER throwing away errors. To work around this check subscriber.isDisposed() before calling onError or use RxJava 2.1.1's new subscriber.tryOnError.
if (!subscriber.isDisposed()) {
subscriber.onError(exception)
}
If you are using rxjava2, please add this in your initialisation code
RxJavaPlugins.setErrorHandler(t -> {
logger.log(Level.SEVERE,null, t);
});
Hope it helps

How does JVM handle runtime exception in RMI remote method?

I have been trying to find out how JVM handles runtime exception in RMI remote methods. I have a remote method that contains the following two methods:
doSomething(
print "doSomething thread id " + Thread.currentThread.getId()
)
fail(){
print "fail thread id " + Thread.currentThread.getId()
throw new RunTimeException
}
The behavior I saw was that even if method fail() is invoked, the thread on which the runtime exception was thrown is still not terminated. A sample output is:
fail thread id 16
stacktrace
...
doSomething thread id 16
doSomething thread id 16
The exception is caught. The caller will get a ServerException with your RuntimeException nested in it as the cause. The executing thread doesn't die.

Illegal Access in WebappClassLoader.loadClass

I have a task scheduler implemented in my application. Basically, what i do is schedule some task's to be executed 4 times in a day (like 6 in 6 hours), so the system schedules it to: 00:00, 06:00, 12:00, 18:00.
Ok, i have a class (FlowJobController) which extends the Thread class and in the run() implementation i keep sleeping the thread in 60 to 60 seconds, so it's executed again to check if there's any task to be executed. If true, i run my Job.
Basically the main part it:
rSet = pStmt.executeQuery();
while (rSet.next()) {
long jobId = rSet.getLong("trf_codigo");
String ruleName = rSet.getString("reg_nome");
String ruleParameters = rSet.getString("trf_regra_parametros");
Job job = new Job();
job.setId(jobId);
job.setRuleName(ruleName);
job.setParameters(Functions.stringToList(ruleParameters, "\n"));
FlowJob flowJob = new FlowJob(this, job);
flowJob.start();
}
} catch (Exception ex) {
logger.error(WFRSystem.DEFAULT_USER, system.getCode(), ex);
} finally {
try {
DBConnection.close(pStmt);
DBConnection.close(rSet);
// executede 60 in 60 sec
Thread.sleep(60 * 1000);
} catch (InterruptedException ex) {
logger.error(WFRSystem.DEFAULT_USER, system.getCode(), ex);
}
}
The thing is: When the pStmt.executeQUery() returns records to be executed, it goes into the while and the error appears into the line: Job job = new Job();
The error is:
Exception in thread "FlowJobController" java.lang.NoClassDefFoundError: wfr/com/Job
at wfr.com.FlowJobController.run(FlowJobController.java:112)
Before this error i got this error:
25/09/2012 12:00:09 org.apache.catalina.loader.WebappClassLoader loadClass
INFO: Illegal access: this web application instance has been stopped already. Could not load wfr.com.Job.
The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
java.lang.IllegalStateException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1566)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at wfr.com.FlowJobController.run(FlowJobController.java:112)
The FlowJobController.java:112 is the Job job = new Job();
What am i doing wrong?
The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.
If you are saying that your code deliberately threw the IllegalStateException exception, then that is the likely cause of the subsequent problems. If you throw an uncheck exception in static initialization, and that exception propagates, then the class initialization fails, and the class (and all classes that depend on it) are unusable. In this case, it looks like it also caused the webapp to be stopped.
If this is the problem, the solution is "don't do that". Fix whatever is causing the exception to be thrown.
The other possibility is that this is simply a missing class problem:
Well, that sounds not possible (to not be in the war) since i'm running into the eclipse environment and it's in the class folder directory and no errors is shown about not finding those classes...
The class loader won't be looking in the Eclipse classes folder. It will be looking in the webapp directory on your web container (Tomcat, Jetty, whatever).

Categories