I suddenly got a weird problem in my application, but I am not sure if I can isolate the issue. I couldn't reproduce the bug in a SCCEE, but maybe someone could help me understand what happens by answering the 2 questions below.
The Context:
I have, basically this:
...
Some treatment
->call to json-io to parse a Json String to Java Objects. see below
...
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
myUI.start();//starts my user interface
}
});
Usually, everything goes fine. But I added to the treatments a call to Json IO (a library that parses Json to Java and that I generally use without any trouble).
Now, one of my other library is yelling:
Caused by: java.lang.NullPointerException
at net.sourceforge.jeuclid.elements.support.ClassLoaderSupport.loadClass(ClassLoaderSupport.java:65)
After some researches, I discovered that it is because Thread.currentThread().getContextClassLoader() returns null.
I went to the run() above and discovered that the only difference between the 2 executions is that the Event Dispatched Thread that used to belong to the group main now belongs to system:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println(Thread.currentThread());
//returns Thread[AWT-EventQueue-0,6,system] instead of Thread[AWT-EventQueue-0,6,main]
myUI.start();//starts my user interface
}
});
In the end, I could solve the problem with
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
myUI.start();//starts my user interface
}
}
});
The Questions:
1) What kind of things can make the EDT change group ?
2) What are the consequences of writing Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); ? Is it a good or a bad idea ?
If your invocation of SwingUtilities.invokeLater is the first action that relies on the presence of the EDT, that thread will be created as a byproduct. So the created thread inherits the thread group of the thread which created it, e.g.
ThreadGroup tg=new ThreadGroup("foo");
new Thread(tg, ()->
SwingUtilities.invokeLater(() -> System.out.println(Thread.currentThread()))
).start();
when performed as first action of an application, will print
Thread[AWT-EventQueue-0,6,foo]
as you can verify on Ideone.
But note that the thread group has no impact on the context class loader, it’s rather a symptom of the same cause. The context class loader is just inherited exactly like the thread group when the thread is created, e.g.
ClassLoader dummyLoader=new URLClassLoader(new URL[0]);
Thread.currentThread().setContextClassLoader(dummyLoader);
SwingUtilities.invokeLater(() ->
System.out.println(Thread.currentThread().getContextClassLoader()==dummyLoader));
will print true; (verify on Ideone).
So apparently, the context loader of the thread which invokes SwingUtilities.invokeLater, initiating the EDT creation, is already null (and that thread is in the system group). Setting the context loader to ClassLoader.getSystemClassLoader() means setting it to its default, so it has no negative impact unless you encounter an environment where the context loader is intentionally set to a non-default loader, though null can not be considered to be such a case. In other words, identifying the place, where it is set to null and fixing that, is the better choice.
Related
I have an OSGI bundle of a following structure:
//...
public ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
//...
#Activate
public void activate() {
executor.submit(new Runnable() {
#Override
public void run() {
//call 3 functions and log the data
}
}
}
#Deactivate
public void deactivate(){
//call 2 other functions
}
The executor in the activate method makes sure that 3 functions are called in a separate from all other bundles thread, because those functions actually implement some sophisticated Windows-message-loop, i.e. a while true loop, that's why, in order not to block other bundles, it is activated in a separate thread. Now what I've sadly noticed, that in order to run 2 functions in deactivate method I need to run them in the same thread, in which 3 functions in activate method were run. Simply speaking, I need to be sure, that activate and deactivate methods of my bundle run in the one same thread, but still to keep this bundle activation separated (in an own thread) from the other bundles.
My question is: how to implement this?
I am not a guru in concurrency in Java, I've tried simply to call this executor in the deactivate method too but I don't know how to do it with one Runnable task, since in deactivate I have only to call 2 functions and in activate only 3 functions and no other calls should be made.
UPD: sorry, I forgot to mention, that there is a routine in another bundle, which calls in certain situations context.getBundle(0).stop() in order to call a deactivation for all bundles. If I want just to add the same submit routine in the deactivate method as is in activate, then in such situation I could clearly see, that those 2 functions from deactivate method of my bundle in the submit's body were not called.
Simply do another executor.submit in deactivate. As it is a single threaded executor it will make sure only one thread processes both.
The only question is how to shut down the executor reliably. Normally after deactivate a component should have closed all its resources.
This sounds like a very common problem. I would just make it explicit you're using a thread and use the methods in Thread that were designed for this. At activate you start the thread, at deactivate you interrupt it. Your main loop watches the interrupt status and executes your deactivate functions after it is interrupted. After interrupt, it is best to join the thread to ensure your activate() method does not return before the background thread has finished running your deactivate functions.
Since exiting the framework (stopping bundle 0) must stop all bundles, and a stopped bundle will deactivate its components, this should all work.
public class Foo extends Thread {
#Activate void activate() { start(); }
#Deactivate void deactivate() throws Exception { interrupt(); join(); }
public void run() {
while(!isInterrupted()) try {
... your 3 function loop
} catch( InterruptedException e) {
break;
}
... 2 deactivate functions
}
}
I have defined this kind of Android Java class, where native function baresipStart() never terminates:
package com.tutpro.baresip;
public class BaresipThread extends Thread {
public void start() {
baresipStart();
}
public void kill() {
baresipStop();
}
public native void baresipStart();
public native void baresipStop();
}
I then call its start() function from another Java class:
BaresipThread thread;
thread = new BaresipThread();
thread.start();
The result is that baresipStart() function starts to run fine, but rest of the application becomes completely unresponsive.
Why is that and how to fix the code so that baresipStart() function runs in the background without stopping all other activity?
Thread.start() is responsible for actually creating the new thread of execution and setting it running. By overriding it as you did, you cause it to instead run baresipStart(), in the thread that invokes start().
Instead of overriding start(), you should override run(). This method is what defines the work to be performed in the new thread of execution.
Furthermore, if native method baresipStart() indeed never returns then you have a problem. Your application cannot terminate while it has any active threads. Supposing that you intend for baresipStop() to cause the thread to finish, you should arrange for baresipStart() to return (or to throw an unchecked exception) when execution is terminated by an invocation of baresipStop(). Do be aware, however, that those native methods need to be thread-safe, because they will, perforce, be invoked by different Java threads.
Thanks for your explanation. I got the new baresip thread started by removing BaresipThread object altogether and replacing the three lines above with this:
new Thread(new Runnable() {
public void run() {
baresipStart();
}
}).start();
User can stop the resulting process via its user interface after which the application is terminated.
x I have overriden the LifecycleBase.start() method like the following. but in Catalina 8.x this method has become final.
Could anyone tell me how to solve this Problem please.
Here is the sourcecode
public void start() throws LifecycleException
{
super.start();
if(condition)
{
File checkDataFile = new File(DataFilePath);
if(containerLog.isDebugEnabled())
containerLog.debug("checking secureDataFile: " + checkDataFile.getAbsolutePath());
another code ...
}
else
{
throw new LifecycleException("illegal arguments");
}
}
public void stop() throws LifecycleException
{
// sync via realm-object -> so the stop-event has to wait for active threads finishing their operations
synchronized(this)
{
super.stop();
}
}
You may use startInternal() and stopInternal(), both methods are abstract protected and are called respectively by start() and stop() .
Of course don't call super.start() and super.stop() or you are in for a StackOverflowError, since start() and stop()are already calling your custom "internal" methods.
Also read carefully the contract from these two methods :
startInternal()
Sub-classes must ensure that the state is changed to org.apache.catalina.LifecycleState.STARTING during the execution of
this method. Changing state will trigger the
org.apache.catalina.Lifecycle.START_EVENT event. If a component fails
to start it may either throw a org.apache.catalina.LifecycleException
which will cause it's parent to fail to start or it can place itself
in the error state in which case stop() will be called on the failed
component but the parent component will continue to start normally
and
stopInternal()
Sub-classes must ensure that the state is changed to
org.apache.catalina.LifecycleState.STOPPING during the execution of
this method. Changing state will trigger the
org.apache.catalina.Lifecycle.STOP_EVENT event.
If you want to see what happens with more details, look at the code of
one of the latest versions of
org.apache.catalina.util.LifecycleBase .
I want to use dependency injection for my Swing UI components in a Spring-Boot application and having a hard time figuring out, how to properly execute the UI behavior on the Event Dispatch Thread.
What I came up with first was like this:
App
#SpringBootApplication
public class App {
private static AppView view;
#Bean
public AppView appView() {
return view;
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(() -> view = new AppView());
SpringApplication app = new SpringApplication(App.class);
app.run(args);
}
}
AppView
public class AppView extends JFrame {
...
#Inject
private DependencyWithTimeConsumingOperations backendController;
#Inject
private JPanel someChildComponent;
#PostConstruct
public void init() {
constructView(); // inits frame properties and child components
showView();
}
private void showView() {
SwingUtilities.invokeLater(() -> {
pack();
setVisible(true);
});
}
...
}
The backend dependency gets called when certain UI events occur. What I observe is, that the backend calls get excuted on the EDT instead of the main application thread, which is bad, I assume. As I understand, not having much experience with Swing, is, that only UI updates should be executed on the EDT.
Is there a better way to wire my dependencies so that everything is executed in its proper thread? What I could find out so far seems a bit outdated or I plainly did not understand the answers :-)
Not sure if it is still relevant to you after so long :), but since it may help others, I'll try to answer.
Spring is only injecting the objects, it is not managing the threads. The behaviour would be the same if you'd instantiated and set the backendController manually, meaning that the EDT (or any thread that is calling the operation) would be the one to execute the code on the controller.
If you explicitly want to run in a different thread, we'd need to know more about the methods in the controller. Are they methods that you want to call and not wait for a reply (fire and forget)? Or maybe you need the reply but can run more than one at the same time? In these scenarios you can take advantage of the Executors class and do something like:
Executors.newSingleThreadExecutor().execute(() -> backendController.timeConsumingOperation1()); // Fire and forget. The operation timeConsumingOperation1 will be executed by a separate thread and the EDT will continue to the next line (won't freeze your GUI)
If you need a result, you may submit it to the pool and poll for the result (maybe with a "refresh" button on the screen). Keep in mind that as soon as you call "get()" the current thread will wait for the pooled thread to finish before proceeding to the next line.
Future result = Executors.newSingleThreadExecutor().execute(() -> backendController.timeConsumingOperation2);
result.isDone(); // You can add a "refresh" button or a scheduled task to check the state...
doSomething(result.get()); // This will hold the current thread until there is a response from the thread running the timeConsumingOperation
Or maybe you do want to freeze the GUI until you have a response from all methods called in the controller, but they can be safely called in parallel:
ExecutorService executorService = Executors.newFixedThreadPool(2);
List<Future<Object>> results = executorService.invokeAll(
Arrays.asList(() -> backendController.timeConsumingOp3(), () -> backendController.timeConsumingOp4));
results.forEach(e -> doSomething(e.get())); // The tasks will be executed in parallel and "doSomething()" will be called as soon as the result for the given index is available
executorService.shutdown(); // Always shutdown
Of course this is just an example, but in large Swing applications it is good practice to create pools of threads (shared by the controllers) to which we submit our long running tasks. You can configure the pool size based on the number of cores (Runtime.getRuntime().availableProcessors()) to best use the resources available on the machine (the tasks submitted will be queued up with no restriction, but only X threads will execute the tasks in parallel, where X is the pool size).
Just use code
SpringApplicationBuilder(Main.class).headless(false).run(args);
do you happen to know explanation why java security manager doesn't forbid creating new threads or starting them? new FileWriter is under security manager, but neither new Thread(), nor threadInstance.start() isn't uneder security manager, and are possible to call.
Wouldn't it be usefull to forbid it ?
Would it be hard to implement ?
Or creating and starting new Thread isn't so relevant to forbid it?
It isn't possible to define a security policy that will prevent code from creating and starting a new thread using the standard Java SecurityManager.
Let's say you have the following code:
public class Test {
public static void main(String [] args) {
System.out.println(System.getSecurityManager() != null ? "Secure" : "");
Thread thread = new Thread(
new Runnable() {
public void run() {
System.out.println("Ran");
}
});
thread.start();
}
}
and you run it with the following command:
java -Djava.security.manager -Djava.security.policy==/dev/null Test
it will run just fine and output:
Secure
Ran
even though we set the security policy to /dev/null, which will grant zero permissions to any code. It's therefore impossible to grant fewer permissions to prevent the code from creating that thread.
This is because the the standard java.lang.SecuritManager only performs an permission check if code tries to create a thread in the root ThreadGroup. At the same time, the SecurityManager's getThreadGroup mehtod always returns the current Thread's thread group, which will never be the root thread group, so permission to create a new Thread will always be granted.
One way to get round this is to subclass java.lang.SecurityManager and override the getThreadGroup method to return the root ThreadGroup. This will then allow you to control whether code can create threads based on whether it has the java.lang.RuntimePermission "modifyThreadGroup".
So if we now define a subclass of SecurityManager as follows:
public class ThreadSecurityManager extends SecurityManager {
private static ThreadGroup rootGroup;
#Override
public ThreadGroup getThreadGroup() {
if (rootGroup == null) {
rootGroup = getRootGroup();
}
return rootGroup;
}
private static ThreadGroup getRootGroup() {
ThreadGroup root = Thread.currentThread().getThreadGroup();
while (root.getParent() != null) {
root = root.getParent();
}
return root;
}
}
and then run our command again, but this time specifying our subclassed ThreadSecurityManager:
java -Djava.security.manager=ThreadSecurityManager -Djava.security.policy==/dev/null Test
We get an exception in our Test class when we try to create the new thread:
Exception in thread "main" java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "modifyThreadGroup")
There is an access check performed in the Thread constructor to see if the caller has permission to change the ThreadGroup that the new thread would be added to. That is how you would implement a security policy to forbid creation of new threads.
(And there is another check on the creation of ThreadGroups ... that checks if you have permission to add the new group to its parent.)
So to answer your questions:
Why java security manager doesn't forbid neither creating new Thread() nor starting it?
The reason is that your JVM's current security policy allows the parent thread to modify its ThreadGroup. You should be able to modify that policy setting to prevent that, and hence prevent creation of child threads.
Wouldn't it be useful to forbid it?
It is. It is unwise to allow untrusted code to create / start threads because: 1) threads once started cannot be safely killed, and 2) creating / starting lots of threads can bring the JVM (and maybe the OS) to its knees.
Would it be hard to implement?
From your perspective, just change the policy.