Chris said:
First of all, heavyweight components are not really all that resource-
hungry. The word sounds that way, and a good number of people are
willing to take their perception of an issue and pass it on as truth to
the next person they meet (or the next person who reads their book or
visits their web site). The "heavyweight" in a heavyweight component
refers to its being drawn as part of the platform's event dispatch
rather than the amount of resources required.
The Java API docs describe it as something very close to "lightweight
components do not have a native peer" where a "peer" is a native GUI
component used by the Java component to perform drawing on the actual
system hardware. If you are rendering on a system device then there
must be a heavyweight component at the top of the containment hierarchy,
because Java code cannot touch the native system devices itself.
The question of resource usage is not really about individual
components, but rather about a whole GUI. A GUI built from all
heavyweight components has, by definition, one native peer for each
component. A GUI built from mostly lightweight components has only one
or a few native peers overall, and therefore _is_ less demanding of
native resources.
That said, there are certainly cases in which heavyweight resources will
be slower than lightweight components. In fact, I really don't
understand why you would say that native components "should" provide
better performance. In fact, native components - just like lightweight
components - have to draw themselves and do other work to make
themselves work... and there's not necessarily anything magical about
the platform that allows code written in the platform's standard
libraries to be faster than the same code written in the application.
Just so.
The chief difference in performance, really, comes from when the
JNI/Java boundary is crossed. If there's a lot of complex repainting
going on - especially without double-buffering, then a heavyweight
component will probably win in performance, because a lightweight
component crosses that boundary for every call to Graphics.xxx. In
normal operation, though, lightweight components will tend to perform
better by performing most of their tasks without having to cross the JNI
boundary to make native calls to the system libraries.
I don't think it's quite that simple, although Chris nailed part of the
issue with regard to JNI/Java. As I understand it, when displaying
itself a lightweight component will use the Graphics provided by the
nearest (containment-wise) heavyweight component up the hierarchy,
thereby making use of that component's native peer. As far as I can
tell and judge, this is no better or worse than a heavyweight component
using it directly.
I distinguish "displaying itself" from "painting itself", however, as
lightweight components may not render directly onto the native peer when
they paint -- Swing components, for example, double-buffer (on the Java
side) by default when they paint, so they paint to memory first then
display. There may be other mechanisms by which lightweight components
may conserve usage of the appropriate peer. For that reason, in
principle lightweight components may indeed perform better because they
can make _fewer_ calls across the JNI boundary to the native peer.
In practice that only applies to components that perform custom drawing
-- if there is a native equivalent (e.g. a button, label, or text field
widget) then a heavyweight that delegates to such a component doesn't
need to use its Graphics on the Java side at all. This is, I think,
what Chris was talking about in his last paragraph.
John Bollinger
(e-mail address removed)