Aha, my trolling friend, it seems Leknor has explained for you why this should be the case more clearly. It is an ambiguous behaviour and it's certainly undocumented and ought to be fixed as you can break a VM irrevocably in this way.

Will LWJGL open and manage its own windows? Can I set caption text, min/max/buttons, what's about (modal) dialogs? Browsing over the doc (only a few seconds I admit) I didn't find this functionallity.

Quote

If you want to mix a Java GUI with high-performance OpenGL, use GL4Java and AWT or Swing.

Cas, why do you think that SWT wouldn't be an option to be mixed with LWGL. I thought, that your library would be kind-of a replacement for GL4Java, some way to get accelerated graphics for Java. Having some "traditional" GUI framework might help to speed up development.

Or let me ask a different question: Let's say I'd like to create something like the original Warcraft or Battle Isle (both not requiring fancy 3D graphics) game. What would be the best approach in Java. Let's further say, Windows is the most important platform and Linux would be a nice to have.

Quote

If you want to write productivity applications then SWT will probably work just as well as AWT.

Definitely better than AWT. Not so sure about Swing though. Here it depends on your requirements which one has more advantages.

LWJGL is a replacement for the entire windowing feature of an OS. It turns your PC into a "console", with a screen, speakers, and some input devices, and that's just about all. As such it doesn't integrate with any notion of a windowing system, so SWT and AWT are redundant. You have to write your own - I have, it took about a month to make it perfect. Various others have experimented with writing realtime rendered GUIs too, all with great success. It's a lot easier than it looks.

If you're creating Warcraft in Java then I suspect that a system with enough poke to run Java will probably also be modern enough to have an OpenGL compatible card so I'd go for LWJGL myself But these days the AWT with its new VolatileImage is producing simple graphics at full speed, if a little buggily. I prefer GL because it lets me scale, rotate, and blend sprites with no noticeable performance degradation.

Although I am wondering whether we need a special 2D interface into LWJGL because there's some plenty fast cards out there that basically have broken OpenGL drivers and don't work as advertised, or for a lot of laptops there is no GL but there's speedy 2D, and that's quite annoying for 2D only stuff.

Lol, you invoked the "troll-net", because I demonstrated the relevant problem with threads that you just don't seem to get. That's amusing. I know you hate to admit you're wrong to KevDog, but isn't this pushing it?

it seems Leknor has explained for you why this should be the case more clearly.

Leknor didn't demonstrate anything beyond which I already said.

It is an ambiguous behaviour and it's certainly undocumented and ought to be fixed as you can break a VM irrevocably in this way.

It's a bug in the VM, you yahoo. If you would take the 30 seconds, you could find it in the bug database. As to how you can "break" a VM with this bug, I don't know. You can certainly leak memory to your heart's content - which is the point KevDog was trying to make.

All of this doesn't address the fact, that it is entirely superfluous and wrong-headed to subclass Thread to implement the Runnable interface for SwingUtilities.invoke*. If you can't see that, there is little hope for you.

rreyelts, will you learn to stfu and READ a post for once? Did you notice in my post I said:

Quote

Runnable just says your class must implement a method named run(). Threads have nothing to do with it. invokeLater() is just using the appropriate interface for clients to implement if they want some action performed later.

And then you go on to say in response:

Quote

SwingUtilities.invokeLater() only asks for a Runnable, because it's not going to create a new thread - it's just going to execute the Runnable on the event thread.

We are saying the same thing with respect to invokeLater(), which is you only need to pass it a referenence to a Runnable object wich should be garbage collected afterwards. Threads have been shown to hang around in the VM without starting them, Whoopiee! Give that man a medal.

The only explanation for this behavior i can determine is that start() will perform some cleanup after the run() method returns. I imagine other peer-dependent objects that are created but not used (sockets? windows?) will also exhibit this behavior because they need an explicit call to a cleanup methods (such as dispose() or something) to have the peer released. Moral of the story here is don't create threads you don't use.

I think the implementation of thread is flawed, it shouldn't create any peer-level objects (os threads) until start() is called (less chance of objects being orphaned). but, i guess it makes thread pooling faster if peer-level objects are created at instantiation time instead of at start time.

Here's some quoting to satisfy you Chris. (I thought I already did that enough, but apparently not for your tastes).

Cas: Er, Kevdog, Thread is a Runnable - I suggest you go and find out what the bug is in your code and change your advice!

Herkules: Yes, but a Runnable is not a Thread. And a Runnable is sufficient. So kevdogs advice is deeply true

KevDog: Yep, a Thread is a Runnable, but a Runnable is not a Thread Thread has a lot more overhead.

So, what we see here is Cas telling KevDog that he's written buggy code. KevDog explains that his code is not buggy and he and Herkules both make the point that Thread has more overhead than Runnable - it should therefore not be used in preference to directly implementing Runnable.

My main point was don't use Thread or a subclass of Thread for the invoke functions.

Threads become active when they are created (with new) and not when they are started (you can run Thread.activeCount() after creating a new one). Active threads are not garbage collected, so if you never run start() they will never be garbage collected. Whether this is a bug in the JVM or not, I don't know (and don't want to read the JVM spec to find out ) but that's the way it currently is.

When I first encountered this, I thought it was a JVM bug in JDK 1.1.8 (we're a bit behind the times!). I tried a sample on JDK 1.4.0 and it still had the same behaviour, so I assumed it wasn't a bug and was just the way it works.

I changed all the Thread subclasses to Runnable subclasses and all the thread leaks went away. We no longer have 10,000-50,000 threads hanging around in memory unrun.

There are only 10 types of people, those who understand binary and those who don't!

You guys should read Thread.java distributed with any JDK from SUN. It clearly shows that after creation, a thread will be added to a ThreadGroup. Only after start() is called, the private exit() will be called from native part. exit() removes the thread from the ThreadGroup which makes the thread garbage collectable.

Construction of a Thread() with no parameters, it says in the JDK docs, is the same as passing null as the threadgroup, so it shouldn't be referenced by any ThreadGroup. It's a hole that needs patching all right.

If the ThreadGroup passed to Thread construction is null, the group of currentThread() will be used. Anyway, you can __not__ create a thread which no group associates with. That's the current implementation from SUN.

Allocates a new Thread object. This constructor has the same effect as Thread(null, target, gname), where gname is a newly generated name. Automatically generated names are of the form "Thread-"+n, where n is an integer.

Quote

1 2 3

publicThread(ThreadGroupgroup, Runnable target, String name)

Allocates a new Thread object so that it has target as its run object, has the specified name as its name, and belongs to the thread group referred to by group. If group is null and there is a security manager, the group is determined by the security manager's getThreadGroup method. If group is null and there is not a security manager, or the security manager's getThreadGroup method returns null, the group is set to be the same ThreadGroup as the thread that is creating the new thread.

If there is a security manager, its checkAccess method is called with the ThreadGroup as its argument. This may result in a SecurityException.

Yeah, I can read , but where does it say that a default threadgroup is created by the JVM on startup and the main thread is assigned to it? Not in the JVM specs it doesn't. It still looks ambiguously defined; it's hinted at here and there but never explicit. And as we've noted, the side effects are quite serious, leading to a VM crash or OS resource starvation.

Every Java thread is a member of a thread group. Thread groups provide a mechanism for collecting multiple threads into a single object and manipulating those threads all at once, rather than individually. For example, you can start or suspend all the threads within a group with a single method call. Java thread groups are implemented by the ThreadGroup(in the API reference documentation) class in the java.lang package.

The runtime system puts a thread into a thread group during thread construction. When you create a thread, you can either allow the runtime system to put the new thread in some reasonable default group or you can explicitly set the new thread's group. The thread is a permanent member of whatever thread group it joins upon its creation--you cannot move a thread to a new group after the thread has been created.

but where does it say that a default threadgroup is created by the JVM on startup and the main thread is assigned to it?

On the same page as my previous links

Quote

When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically calls the method named main of some designated class).

That, combined with the knowledge quoted above that every thread is assigned a threadgroup, should pretty much close this case.

Someone posted code showing that a bunch of Threads that were created but weren't executed would cause a memory error, even if their references were lost. I will take a look, but I bet that they weren't garbage collected since they were in the default threadgroup, and thus it would still be possible to execute them.

Someone posted code showing that a bunch of Threads that were created but weren't executed would cause a memory error, even if their references were lost. I will take a look, but I bet that they weren't garbage collected since they were in the default threadgroup, and thus it would still be possible to execute them.

That's exactly it. Started without a group they are put into the default ThreadGroup. It is still possible to start them by running Thread.getCurrentThread().getThreadGroup() then enumerating through the threads in the group to start it. Basically it still has a reference to the Thread in the default threadgroup so it is never garbage collected.

It is the way it is supposed to work, but it is very misleading... not well documented... and can cause headaches (don't I know it!). Basically just a "gotcha" when using the invokeXXX() functions.

There are only 10 types of people, those who understand binary and those who don't!

Aye, that's what I was getting at. When you look at it in the wider context of JVM stability, and the even wider one of system stability, you'd be wondering why it isn't dealt with a bit more specifically...

It is still possible to start them by running Thread.getCurrentThread().getThreadGroup() then enumerating through the threads in the group to start it. Basically it still has a reference to the Thread in the default threadgroup so it is never garbage collected.

it is??

last time I looked, ThreadGroup only has methods for getting active Threads, not inactive unstarted Threads

(and there is a sun bug report already highlighting this flaw)

p.s.While trauling the bug database, I was suprised to see the number of confirmed bugs in Thread, that Sun have acknowledged, but arn't about to fix. (something about a fundamental api flaw... )

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org