application manager functionality

My comments in the forums listed below suggest some requirements for two APIs related to client-side Java.

o An application instance manager API that offers a Pure Java method to invoke other Java application instances.

o An application cache API that manages information about the location, version and JRE version requirements of both installed app JARs and Web Start cached JARs. This could possibly be built on top of the prefs API that is new in 1.4.

See the "walpj" comments in these two forums.

http://developer.java.sun.com/developer/bugParade/bugs/4267080.html

http://forum.java.sun.com/thread.jsp?forum=32&thread=149700

For a quick justification for an application instance manager, see Michael Prescott's comments.

http://forums.java.sun.com/thread.jsp?forum=37&thread=69892

For a more detailed justification for the application cache API, see Gerald Bauer's JWS 2.0 petition.

http://www.geocities.com/vamp201/king.html

[1022 byte] By [walpj] at [2007-9-26 2:56:03]
# 1

Here's a more succinct version. This was composed as a comment for bugid:4466510.

===== disclaimer ===

While it's true that J2EE is the most fertile area for Java technology adoption (and the area in which Sun is best positioned to take advantage of its investment), I believe that it would be unwise to abandon the foothold that has been gained on desktops through the applet concept.

===== resource management ===

On the server side, application components are managed by the application server which (traditionally) is run within a single instance of one version of the JVM. In other words, each physical machine runs one virtual machine.

On the client side, each application or Web Start app is run in its own virtual machine instance. So, one physical machine runs multiple virtual machinesone for each application.Overhead (from security, garbage collection and system services infrastructure) is duplicated for each application instance.

Employing one VM instance per application instance allows each Java application to be run in a JRE version for which it has been debugged. It also takes advantage of standard memory management and CPU scheduling provided by the underlying OS.

So what does this have to do with the RFE? *Maybe* (in the 1.4 beta refresh) Sun will sufficiently satisfy this RFE's <sarcasm>modest</sarcasm> demand for a small memory footprint without sacrificing performance. However, I want to discuss some complementary changes to the client-side JRE that could both (a) decrease overhead by reducing redundancy and (b) improve the interoperability of Pure Java applications.

===== proposal overview ===

By adding some application management functionality to the client-side JRE, all apps that are compatible with a given JRE could run in a single VM instance [1]. Recalling the analogy between J2EE and J2SE, just as the appserver creates a smart OS-independent container for managing server-side application components, this proposal envisions a dumb OS-independent container for managing client-side applications.

Applications that are deployed using Web Start already benefit from partial client-side application management. For instance, the JRE version required by a particular Web Start-deployed app is automatically chosen (based on the Web-hosted deployment description for the app).

Hopefully, Sun could leverage the Web Start codebase in other ways too. In my comments to bugid 4267080, I discuss using Web Start JAR management technology to "grow" multiple JRE class libraries on the client in order to decrease the plug-in download time [2].

However, Web Start alone has important failings. For instance, (as far as I know) no Pure Java mechanism exists to enable one Java application or Web Start app to start a second Java application or Web Start app in a JRE for which the second application was debugged.

===== new interface requirements ===

Running all JRE-version-compatible apps in a single VM instance would require at least two new interfaces.

An application instance manager API must offer a Pure Java method to invoke another Java application [3]. It might also provide a method to query other application instances [4]. These interfaces should be compatible with future CORBA ORB integration [5].

An application cache manager API must offer methods to manage information about (a) JAR file locations, (b) app version and (c) JRE requirements for both installed application JARs and Web Start cached JARs [6]. This could possibly be built on top of the prefs API [7].

===== a preliminary list of issues ===

Perhaps this migration route has been explored elsewhere in more depth, but I'll go ahead and list some issues that occur to me.

(a) Can VM implementations for all target OSs avoid unequal CPU cycle allocation for Java apps compared to native apps? What about all other system resource allocation?

(b) Can static security domains be made rich enough to cover the needs of all client applications and applets?

(c) Can a system module based on the current hierarchical ClassLoader architecture, the current security architecture, and the future resource permissions [8] feature provide all of the functionality necessary to securely compartmentalize all resources associated with an application, including memory and threads?

(d) Through what means could the JRE version requirement of an application be updated if the app is updatedwithout requiring the entire set of cached JARs for that app to be expired?

(e) What degree of control will the user be given regarding distribution of installed JARs in the filesystem?

(f) What happens when the JAR cache must be distributed across multiple volumes?

(g) What sort of integration should there be between cache management and the Windows registry, Red Hat's RPM manager, etc.?

(h) Does Sun eventually plan to emphasize either GNOME integration [10] or a Pure Java desktop toward which a migration path should be planned?

===== notes ===

[1]

This forum topic discusses running multiple apps in a single JRE.

http://forum.java.sun.com/thread.jsp?forum=32&thread=151780

[2]

This RFE discusses methods for custom installers and incremental upgrades to support distributing the plug-in to bandwidth-constrained users.

http://developer.java.sun.com/developer/bugParade/bugs/4267080.html

[3]

In this forum topic, Michael Prescott introduced several justifications for an application manager.

http://forums.java.sun.com/thread.jsp?forum=37&thread=69892

[4]

An application manager could eliminate the need for this hack, which eliminates multiple instances of an app.

http://www.absolutejava.com/articles/preventing-multiples-instances-of-a-java-program-from-running-simultaneously.html

[5]

The common object request broker architecture (CORBA) spec from OMG defines language-neutral middleware for distributed computing. Both J2SE and J2EE SKDs include CORBA integration tools. GNOME uses CORBA for component integration.

http://www.corba.org/

http://java.sun.com/j2ee/corba/

[6]

For a more detailed consideration of cache API requirements, see Gerald Bauer's JWS 2.0 petition.

http://www.geocities.com/vamp201/king.html

[7]

The new preferences (prefs) API provides functionality similar to that of the Windows registry.

http://java.sun.com/j2se/1.4/docs/guide/lang/preferences.html

[8]

The 1.4 docs list resource consumption management as a future direction.

http://java.sun.com/j2se/1.4/docs/guide/security/spec/security-spec.doc8.html#20670

[9]

Yes, this is the obligatory Microsoft bash.

[10]

GNOME is an opensource desktop environment that uses CORBA for component integration. Sun supports the GNOME development effort and offers GNOME for Solaris.

http://www.sun.com/software/star/gnome/

walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 2

The following was composed as a Usenet post to speculate about the direction of client-side Java.

Subject: Re: Join the movement to get PC OEMs to put Java on Windows XP

Chris Newman <chris@floor51.com> wrote . . .

>

> This is a truly irresistible argument and I'd like to play devil's

> advocate.

-grin- Those rubbery masks smell pretty bad, don't they?

>

> Do we really need the JRE on XP ? Java has morphed into a

> remarkable enterprise server side/web services architecture built on a

> visionary language design with a fantastically rich set of APIs. Surely

> serious desktop software that needs a virtual machine can just install

> one along with it a bit like the way Java Web Start does. (or live

> inside the Web Start container?)

I'd like to share a Vision of the Future. In this future (set around 2010), upper middle class America has reached bandwidth nirvana at home. But a non-trivial segment of low wage earners and rural residents still use dialup connections. Context-aware voice recognition is finally usable. The PC/notebook/tablet is an integral part of business and student life. Wireless LANs exist in most public venues such as trade shows, limosines, college campuses, airports, museums, etc. Nevertheless, they aren't available everywhere, and bandwidth decreases linearly with the number of users. 3G wireless service is available in major cities, but the per-minute price is still too high for a middle class person to browse the Web daily using it.

So what will a user want? He'll obviously want info and communication on demand from wireless devices. But also, he'll want *his* data available in a recognizable format *wherever he is*. For instance, if he saved a URL in his browser at home, he wants to be able to look it up at work. If he started writing/dictating a note to his insurance company but had to interupt the task in order to pick up his kid from karate, he wants the partially composed message to be available on his PDA. And, preferrably, he wants to be able to edit it using a similar user interface. Basically, he wants quick access to a portable place.

At least three complementary strategies exist for creating portable placeshosting, synchronization and portable objects. Most of today's Web applications (such as Yahoo! Notepad) use only hosting. Most of today's PDAs use only synchronization. Javaspaces features portable objects. But as I said, these three strategies are complementary. For instance, PC Anywhere combines hosting and synchronization.

The dominant strategy for portable places will depend largely on evolution of wireless networking and battery technology. If 3G wireless evolves into cheap, ubiquitous, high-bandwidth connectivity, then pure hosting is the simplest option. Unfortunately, I don't expect that in the near future.

Meanwhile, back at the ranch (er, I mean, in the dual-mode minivan), our busy friend with the PDA is having to wait for an hour between the end of his son's karate class and the end of his daughter's soccer (football) practice. How will today's technologies evolve to serve him?

Java technology could allow an app to be written to provide rich, familiar, portable user interfaces for both connected and non-connected platforms. Any application could feature both J2SE and J2ME versions (with excellent code reuse between the two). And the J2ME version could be updated on the PDA as part of synchronization. Application state could also be transferred. So when our busy father turns on his PDA, the undo feature works, and the cursor is exactly where he left it.

So what does this have to do with applet support in IE for XP? Well, applets are used on many websites. *If* (and this is a big if) that compatibility issue impells OEMs and users to install a Java 2 JRE, then the user base will increase dramatically. That will have two notable effects. First, Web Start will be a more attractive platform for mainstream client-server application deployment (because the large JRE would already be installed). Second, apps and applets *with recognizable user interfaces* built using free Java development tools will move from academia and opensource onto mainstream PCs.

Both of these trends will decrease the average user's reliance on OS-specific applications.

>

> The further MS stays away from it the better but that's not to say I

> dislike MS - I continue to use the Office suite and Exchange because as

> a software developer myself, for all their annoyances, I like them. It's

> just that the Linux environment is a developer's dream with all the

> tools and the feeling of freedom to innovate that I could want so I

> develop and live under Redhat/Debian with KDE2, Mozilla, NetBeans etc

> only booting into Windows for MS Office. And I develop java code

> directly onto the FAT32 partition under Linux so I can point application

> servers at the same file structure under both operating systems no

> problem. Hopefully one day I'll become good enough to contribute to the

> open-source projects like StarOffice, KDE and Helix Gnome.

As for Microsoft keeping its grubby hands off of Java, I agree.

Thanks for mentioning GNOME. For those of you who don't know, the GNOME desktop is gradually reaching feature parity with the Win32 desktop. And it's available for both Linux and Solaris. GNOME is built using CORBA for component integration. CORBA is a language-agnostic and OS-agnostic open standard architecture for distributed computing.

The J2EE and J2SE SDKs ship with tools for CORBA integration. It allows Java components and components written in other languages to interoperate as equals. To make an analogy with .NET development, a CORBA object request broker (ORB) provides the interface between Java "managed code" components and native "unmanaged code" components. Unfortunately, (as far as I know) Microsoft has vastly superior tool support for this sort of integration. (I'm curious how the two compare with regard to runtime overhead.)

Perhaps it's time for Sun to reformulate the Pure Java campaign as the Pure Java Platform campaign to emphasize that native apps are welcome to use Java platform library features in order to facilitate incremental migration. This would take a lot of wind out of the language freedom rhetoric surrounding .NET. As you say, Linux provides a great environment for developers. Augmenting it with Java "managed code" helps it maintain feature parity with .NET tools.

>

> Anyhow, if I was setting up a server I'd install the latest JDK straight

> from java.sun.com with all the extra jars like xalan/xerces and so on,

> no way using the default installation. So the only thing that is really

> affected is web browser applets under XP. This is not great but then how

> important are applets? (though it will be extremely annoying not to be

> able to use them) With the onset of broadband, internet-enabled TV and

> technology like the Java Web Start, do we really need to be so

> InternetExplorer-centric ?

Digging a channel is often the easiest way to divert a river.

>

> I'd put my money on the proliferation of J2ME in all kinds of mobile

> devices and hope that TV set-top boxes built on Linux would provide

> Java-based APIs for development.

>

> Just ideas :)

>

I see a similar optimistic scenario. Even if applet compatibility doesn't drive Java 2 onto PCs, mobile devices could. Do Japanese Java-enabled mobile phone/PDAs ship with Java technology-based PC synchronization? Or is all state centrally managed (using Sun hardware) and served to PCs through a Web application?

More ideas concerning client-side Java can be found in the following forums. I post as "walpj".

This request for enhancement explores incremental upgrade strategies.

http://developer.java.sun.com/developer/bugParade/bugs/4267080.html

This forum topic explores application management and resource management. It contains my response to bugid 4466510.

http://forum.java.sun.com/thread.jsp?forum=25&thread=156163

walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 3

I took a look at the 1.3.0 source to find out what handles security for applets. Apparently sun.awt.SunToolkit.createNewAppContext() loads the applet class and gives it a sun.awt.AppContext. An AppContext bundles an AWT EventQueue and a ThreadGroup associated with the applet.

So, part of the application instance manager API would expose createNewAppContext(). Also, AppContext must be generalized to group all resources associated with an app, including a ClassLoader.

BTW, another class named AppContext (javax.swing.AppContext) also exists in the 1.3.0 source, but I haven't tried to discover how it's related.

For reference, I've included some source. Note that this source code is covered by Sun's community source license.

http://www.sun.com/software/communitysource/java2/licensing.html

===== sun.awt.SunToolkit.createNewAppContext() method ===

/*

* Create a new AppContext, along with its EventQueue, for a

* new ThreadGroup. Browser code, for example, would use this

* method to create an AppContext & EventQueue for an Applet.

*/

public static AppContext createNewAppContext() {

ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();

EventQueue eventQueue;

String eqName = Toolkit.getProperty("AWT.EventQueueClass",

"java.awt.EventQueue");

try {

eventQueue = (EventQueue)Class.forName(eqName).newInstance();

} catch (Exception e) {

System.err.println("Failed loading " + eqName + ": " + e);

eventQueue = new EventQueue();

}

AppContext appContext = new AppContext(threadGroup);

appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue);

PostEventQueue postEventQueue = new PostEventQueue(eventQueue);

appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);

return appContext;

}

===== sun.awt.AppContext class ===

/*

* @(#)AppContext.java1.21 00/02/02

*

* Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved.

*

* This software is the proprietary information of Sun Microsystems, Inc.

* Use is subject to license terms.

*

*/

package sun.awt;

import java.awt.Frame;

import java.awt.Toolkit;

import java.awt.event.InvocationEvent;

import java.security.AccessController;

import java.security.PrivilegedAction;

import java.util.Hashtable;

import java.util.Enumeration;

import java.awt.datatransfer.Clipboard;

/**

* The AppContext is a table referenced by ThreadGroup which stores

* application service instances. (If you are not writing an application

* service, or don't know what one is, please do not use this class.)

* The AppContext allows applet access to what would otherwise be

* potentially dangerous services, such as the ability to peek at

* EventQueues or change the look-and-feel of a Swing application.<p>

*

* Most application services use a singleton object to provide their

* services, either as a default (such as getSystemEventQueue or

* getDefaultToolkit) or as static methods with class data (System).

* The AppContext works with the former method by extending the concept

* of "default" to be ThreadGroup-specific. Application services

* lookup their singleton in the AppContext.<p>

*

* For example, here we have a Foo service, with its pre-AppContext

* code:<p>

* <code><pre>

*public class Foo {

*private static Foo defaultFoo = new Foo();

*

*public static Foo getDefaultFoo() {

*return defaultFoo;

*}

*

*... Foo service methods

*}</pre></code><p>

*

* The problem with the above is that the Foo service is global in scope,

* so that applets and other untrusted code can execute methods on the

* single, shared Foo instance. The Foo service therefore either needs

* to block its use by untrusted code using a SecurityManager test, or

* restrict its capabilities so that it doesn't matter if untrusted code

* executes it.<p>

*

* Here's the Foo class written to use the AppContext:<p>

* <code><pre>

*public class Foo {

*public static Foo getDefaultFoo() {

*Foo foo = (Foo)AppContext.getAppContext().get(Foo.class);

*if (foo == null) {

*foo = new Foo();

*getAppContext().put(Foo.class, foo);

*}

*return foo;

*}

*

*... Foo service methods

*}</pre></code><p>

*

* Since a separate AppContext can exist for each ThreadGroup, trusted

* and untrusted code have access to different Foo instances. This allows

* untrusted code access to "system-wide" services -- the service remains

* within the AppContext "sandbox". For example, say a malicious applet

* wants to peek all of the key events on the EventQueue to listen for

* passwords; if separate EventQueues are used for each ThreadGroup

* using AppContexts, the only key events that applet will be able to

* listen to are its own. A more reasonable applet request would be to

* change the Swing default look-and-feel; with that default stored in

* an AppContext, the applet's look-and-feel will change without

* disrupting other applets or potentially the browser itself.<p>

*

* Because the AppContext is a facility for safely extending application

* service support to applets, none of its methods may be blocked by a

* a SecurityManager check in a valid Java implementation. Applets may

* therefore safely invoke any of its methods without worry of being

* blocked.

*

* Note: If a SecurityManager is installed which derives from

* sun.awt.AWTSecurityManager, it may override the

* AWTSecurityManager.getAppContext() method to return the proper

* AppContext based on the execution context, in the case where

* the default ThreadGroup-based AppContext indexing would return

* the main "system" AppContext. For example, in an applet situation,

* if a system thread calls into an applet, rather than returning the

* main "system" AppContext (the one corresponding to the system thread),

* an installed AWTSecurityManager may return the applet's AppContext

* based on the execution context.

*

* @author Thomas Ball

* @author Fred Ecks

* @version 1.21 02/02/00

*/

public final class AppContext {

/* Since the contents of an AppContext are unique to each Java

* session, this class should never be serialized. */

/* The key to put()/get() the Java EventQueue into/from the AppContext.

*/

public static final Object EVENT_QUEUE_KEY = new StringBuffer("EventQueue");

/* A map of AppContexts, referenced by ThreadGroup.

*/

private static Hashtable threadGroup2appContext = null;

/* The main "system" AppContext, used by everything not otherwise

contained in another AppContext.

*/

private static AppContext mainAppContext = null;

/*

* The hashtable associated with this AppContext. A private delegate

* is used instead of subclassing Hashtable so as to avoid all of

* Hashtable's potentially risky methods, such as clear(), elements(),

* putAll(), etc. (It probably doesn't need to be final since the

* class is, but I don't trust the compiler to be that smart.)

*/

private final Hashtable table;

private final ThreadGroup threadGroup;

private boolean isDisposed = false; // true if AppContext is disposed

static {

// On the main Thread, we get the ThreadGroup, make a corresponding

// AppContext, and instantiate the Java EventQueue. This way, legacy

// code is unaffected by the move to multiple AppContext ability.

AccessController.doPrivileged(new PrivilegedAction() {

public Object run() {

ThreadGroup currentThreadGroup =

Thread.currentThread().getThreadGroup();

ThreadGroup parentThreadGroup = currentThreadGroup.getParent();

while (parentThreadGroup != null) {

// Find the root ThreadGroup to construct our main AppContext

currentThreadGroup = parentThreadGroup;

parentThreadGroup = currentThreadGroup.getParent();

}

mainAppContext = new AppContext(currentThreadGroup);

numAppContexts = 1;

return mainAppContext;

}

});

}

/*

* The total number of AppContexts, system-wide. This number is

* incremented at the beginning of the constructor, and decremented

* at the end of dispose(). getAppContext() checks to see if this

* number is 1. If so, it returns the sole AppContext without

* checking Thread.currentThread().

*/

private static int numAppContexts;

/**

* Constructor for AppContext. This method is <i>not</i> public,

* nor should it ever be used as such. The proper way to construct

* an AppContext is through the use of SunToolkit.createNewAppContext.

* A ThreadGroup is created for the new AppContext, a Thread is

* created within that ThreadGroup, and that Thread calls

* SunToolkit.createNewAppContext before calling anything else.

* That creates both the new AppContext and its EventQueue.

*

* @paramthreadGroupThe ThreadGroup for the new AppContext

* @seesun.awt.SunToolkit

* @sinceJDK1.2

*/

AppContext(ThreadGroup threadGroup) {

numAppContexts++;

table = new Hashtable(2);

if (threadGroup2appContext == null) {

threadGroup2appContext = new Hashtable(2, 0.2f);

}

this.threadGroup = threadGroup;

threadGroup2appContext.put(threadGroup, this);

}

private static MostRecentThreadAppContext mostRecentThreadAppContext = null;

/**

* Returns the appropriate AppContext for the caller,

* as determined by its ThreadGroup. If the main "system" AppContext

* would be returned and there's an AWTSecurityManager installed, it

* is called to get the proper AppContext based on the execution

* context.

*

* @return the AppContext for the caller.

* @seejava.lang.ThreadGroup

* @sinceJDK1.2

*/

public final static AppContext getAppContext() {

if (numAppContexts == 1)// If there's only one system-wide,

return mainAppContext; // return the main system AppContext.

final Thread currentThread = Thread.currentThread();

AppContext appContext = null;

// Note: this most recent Thread/AppContext caching is thread-hot.

// A simple test using SwingSet found that 96.8% of lookups

// were matched using the most recent Thread/AppContext. By

// instantiating a simple MostRecentThreadAppContext object on

// cache misses, the cache hits can be processed without

// synchronization.

MostRecentThreadAppContext recent = mostRecentThreadAppContext;

if ((recent != null) && (recent.thread == currentThread)) {

appContext = recent.appContext; // Cache hit

} else {

appContext = (AppContext)AccessController.doPrivileged(

new PrivilegedAction() {

public Object run() {

// Get the current ThreadGroup, and look for it and its

// parents in the hash from ThreadGroup to AppContext --

// it should be found, because we use createNewContext()

// when new AppContext objects are created.

ThreadGroup currentThreadGroup = currentThread.getThreadGroup();

ThreadGroup threadGroup = currentThreadGroup;

AppContext context =

(AppContext)threadGroup2appContext.get(threadGroup);

while (context == null) {

threadGroup = threadGroup.getParent();

if (threadGroup == null) {

// If we get here, we're running under a ThreadGroup that

// has no AppContext associated with it. This should never

// happen, because createNewContext() should be used by the

// toolkit to create the ThreadGroup that everything runs

// under.

throw new RuntimeException("Invalid ThreadGroup");

}

context = (AppContext)threadGroup2appContext.get(threadGroup);

}

// In case we did anything in the above while loop, we add

// all the intermediate ThreadGroups to threadGroup2appContext

// so we won't spin again.

for (ThreadGroup tg = currentThreadGroup; tg != threadGroup; tg = tg.getParent()) {

threadGroup2appContext.put(tg, context);

}

// Now we're done, so we cache the latest key/value pair.

// (we do this before checking with any AWTSecurityManager, so if

// this Thread equates with the main AppContext in the cache, it

// still will)

mostRecentThreadAppContext =

new MostRecentThreadAppContext(currentThread, context);

return context;

}

});

}

if (appContext == mainAppContext) {

// Before we return the main "system" AppContext, check to

// see if there's an AWTSecurityManager installed. If so,

// allow it to choose the AppContext to return.

SecurityManager securityManager = System.getSecurityManager();

if ((securityManager != null) &&

(securityManager instanceof AWTSecurityManager)) {

AWTSecurityManager awtSecMgr =

(AWTSecurityManager)securityManager;

AppContext secAppContext = awtSecMgr.getAppContext();

if (secAppContext != null) {

appContext = secAppContext; // Return what we're told

}

}

}

return appContext;

}

private long DISPOSAL_TIMEOUT = 5000; // Default to 5-second timeout

// for disposal of all Frames

// (we wait for this time twice,

// once for dispose(), and once

// to clear the EventQueue).

private long THREAD_INTERRUPT_TIMEOUT = 1000;

// Default to 1-second timeout for all

// interrupted Threads to exit, and another

// 1 second for all stopped Threads to die.

/**

* Disposes of this AppContext, all of its top-level Frames, and

* all Threads and ThreadGroups contained within it.

*

* This method must be called from a Thread which is not contained

* within this AppContext.

*

* @exception IllegalThreadStateException if the current thread is

*contained within this AppContext

* @sinceJDK1.2

*/

public void dispose() throws IllegalThreadStateException {

// Check to be sure that the current Thread isn't in this AppContext

if (this.threadGroup.parentOf(Thread.currentThread().getThreadGroup())) {

throw new IllegalThreadStateException(

"Current Thread is contained within AppContext to be disposed."

);

}

synchronized(this) {

if (this.isDisposed) {

return; // If already disposed, bail.

}

this.isDisposed = true;

}

releaseClipboard();

// First, we post an InvocationEvent to be run on the

// EventDispatchThread which disposes of all top-level Frames

final Object notificationLock = new Object();

Runnable runnable = new Runnable() { public void run() {

Frame [] frames = Frame.getFrames();

for (int i = frames.length - 1; i >= 0; i--) {

frames[i].dispose(); // Dispose of all top-level Frames

}

synchronized(notificationLock) {

notificationLock.notifyAll(); // Notify caller that we're done

}

} };

synchronized(notificationLock) {

SunToolkit.postEvent(this,

new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));

try {

notificationLock.wait(DISPOSAL_TIMEOUT);

} catch (InterruptedException e) { }

}

// Next, we post another InvocationEvent to the end of the

// EventQueue. When it's executed, we know we've executed all

// events in the queue.

runnable = new Runnable() { public void run() {

synchronized(notificationLock) {

notificationLock.notifyAll(); // Notify caller that we're done

}

} };

synchronized(notificationLock) {

SunToolkit.postEvent(this,

new InvocationEvent(Toolkit.getDefaultToolkit(), runnable));

try {

notificationLock.wait(DISPOSAL_TIMEOUT);

} catch (InterruptedException e) { }

}

// Next, we interrupt all Threads in the ThreadGroup

this.threadGroup.interrupt();

// Note, the EventDispatchThread we've interrupted may dump an

// InterruptedException to the console here. This needs to be

// fixed in the EventDispatchThread, not here.

// Next, we sleep 10ms at a time, waiting for all of the active

// Threads in the ThreadGroup to exit.

long startTime = System.currentTimeMillis();

long endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT;

while ((this.threadGroup.activeCount() > 0) &&

(System.currentTimeMillis() < endTime)) {

try {

Thread.sleep(10);

} catch (InterruptedException e) { }

}

// Then, we stop any remaining Threads

this.threadGroup.stop();

// Next, we sleep 10ms at a time, waiting for all of the active

// Threads in the ThreadGroup to die.

startTime = System.currentTimeMillis();

endTime = startTime + (long)THREAD_INTERRUPT_TIMEOUT;

while ((this.threadGroup.activeCount() > 0) &&

(System.currentTimeMillis() < endTime)) {

try {

Thread.sleep(10);

} catch (InterruptedException e) { }

}

// Next, we remove this and all subThreadGroups from threadGroup2appContext

int numSubGroups = this.threadGroup.activeGroupCount();

if (numSubGroups > 0) {

ThreadGroup [] subGroups = new ThreadGroup[numSubGroups];

numSubGroups = this.threadGroup.enumerate(subGroups);

for (int subGroup = 0; subGroup < numSubGroups; subGroup++) {

threadGroup2appContext.remove(subGroups[subGroup]);

}

}

threadGroup2appContext.remove(this.threadGroup);

MostRecentThreadAppContext recent = mostRecentThreadAppContext;

if ((recent != null) && (recent.appContext == this))

mostRecentThreadAppContext = null;

// If the "most recent" points to this, clear it for GC

// Finally, we destroy the ThreadGroup entirely.

try {

this.threadGroup.destroy();

} catch (IllegalThreadStateException e) {

// Fired if not all the Threads died, ignore it and proceed

}

this.table.clear(); // Clear out the Hashtable to ease garbage collection

numAppContexts--;

}

private MostRecentKeyValue mostRecentKeyValue = null;

/**

* Returns the value to which the specified key is mapped in this context.

*

* @paramkeya key in the AppContext.

* @return the value to which the key is mapped in this AppContext;

* <code>null</code> if the key is not mapped to any value.

* @see#put(Object, Object)

* @sinceJDK1.2

*/

public Object get(Object key) {

// Note: this most recent key/value caching is thread-hot.

// A simple test using SwingSet found that 72% of lookups

// were matched using the most recent key/value. By instantiating

// a simple MostRecentKeyValue object on cache misses, the

// cache hits can be processed without synchronization.

MostRecentKeyValue recent = mostRecentKeyValue;

if ((recent != null) && (recent.key == key))

return recent.value;

Object value = table.get(key);

mostRecentKeyValue = new MostRecentKeyValue(key, value);

return value;

}

/**

* Maps the specified <code>key</code> to the specified

* <code>value</code> in this AppContext. Neither the key nor the

* value can be <code>null</code>.

* <p>

* The value can be retrieved by calling the <code>get</code> method

* with a key that is equal to the original key.

*

* @paramkeythe AppContext key.

* @paramvaluethe value.

* @returnthe previous value of the specified key in this

* AppContext, or <code>null</code> if it did not have one.

* @exception NullPointerException if the key or value is

*<code>null</code>.

* @see#get(Object)

* @sinceJDK1.2

*/

public Object put(Object key, Object value) {

MostRecentKeyValue recent = mostRecentKeyValue;

if ((recent != null) && (recent.key == key))

recent.value = value;

return table.put(key, value);

}

/**

* Removes the key (and its corresponding value) from this

* AppContext. This method does nothing if the key is not in the

* AppContext.

*

* @paramkeythe key that needs to be removed.

* @return the value to which the key had been mapped in this AppContext,

* or <code>null</code> if the key did not have a mapping.

* @sinceJDK1.2

*/

public Object remove(Object key) {

MostRecentKeyValue recent = mostRecentKeyValue;

if ((recent != null) && (recent.key == key))

recent.value = null;

return table.remove(key);

}

/**

* Returns the root ThreadGroup for all Threads contained within

* this AppContext.

* @sinceJDK1.2

*/

public ThreadGroup getThreadGroup() {

return threadGroup;

}

/**

* Returns a string representation of this AppContext.

* @sinceJDK1.2

*/

public String toString() {

return getClass().getName() + "[threadGroup=" + threadGroup.getName() + "]";

}

private void releaseClipboard() {

Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();

if ( clip instanceof SunClipboard ) {

((SunClipboard)clip).clearAppContext();

}

}

}

final class MostRecentThreadAppContext {

final Thread thread;

final AppContext appContext;

MostRecentThreadAppContext(Thread key, AppContext value) {

thread = key;

appContext = value;

}

}

final class MostRecentKeyValue {

final Object key;

Object value;

MostRecentKeyValue(Object k, Object v) {

key = k;

value = v;

}

}

walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 4
The sourceforge project jsh manages multiple applications within a single VM.https://sourceforge.net/projects/jsh/
walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 5
The application resource isolation part of this request is being addressed by the following jsr. http://jcp.org/jsr/detail/121.jsp
walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 6
Also, Echidna handles managing multiple app instances in a single VM instance. http://www.javagroup.org/echidna/
walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 7
The latest version of jsh ( http://www.appliweb.net/jsh) uses echidna.
walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 8

This is the best (if somewhat dated) overview that I've found comparing CORBA and .NET component features.

http://www.iit.edu/~huanwei/doc/corba-net.html

And this article says that, as of Sept 2000, the CORBA group of OMG has been working on SOAP and (more specifically) .NET interoperability. I'm eager to see the proposal, but nothing exists on the public CORBA website.

http://www.nwfusion.com/archive/2000/104969_08-21-2000.html

walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 9

While mostly concerned with evaluating existing technologies for the Web Services infrastructure, this whitepaper highlights the complexity and resource overhead associated with generalizing all components as distributed components.

http://www.orchestranetworks.com/us/solutions/0105_whitepaper.cfm

walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 10

With emphasis on its new Model Driven Architecture initiative, OMG appears to have given up on promoting CORBA as the pervasive middleware technology. Undoubtedly there will be IDL mapping for C#, but they might not emphasize integrating .NET-style security context metadata.

http://www.omg.org/mda/

walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 11
Resolving bugid 4080029 is a prerequisite to VM sharing.
walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 12

The following was posted as addendum to previous comments to bugid 4466510.

===== JSR-121 addendum ===

glenn42, I became aware of JSR-121 after writing the diatribe above. Since you mentioned it, I'd like to point out how it could relate to the proposal above.

The API proposed in JSR-121 would cover the application isolation component of the proposal, but it wouldn't address the need for forward compatibility of JREs with legacy Java applications. J2SE is a rapidly evolving platform. Each release includes a nontrivial set of compatibility notes [1]. A complicated migration is fine for server-side applications, but a client-side (or stand-alone) app could be broken by something as seemingly trivial as a change to default widget sizes [2]. Basically, I'm concerned that API documentation is insufficient to allow developers to rely only on features verified by Spec-trak [3]. And I would detest the necessity for JavaCheck [4] to verify an app's *forward* compatibility with new JRE versions.

Realize that the high code reuse that benefits Java platform developers also makes their code particularly susceptible to JRE implementation changes.

I'm calling for implementation of JSR-121 in Sun's client-side JRE, *plus* implementation of APIs that provide a Pure Java mechanism for running a legacy app in a legacy JRE [5].

This comment (with working links) can also be found in the following topic in the JDC forums.

http://forum.java.sun.com/thread.jsp?forum=25&thread=156163

[1]

Here are the compatibility notes accompanying 1.4. Thanks to the welcome addition of generic types, the 1.5 compatibility notes will likely be longer.

http://java.sun.com/j2se/1.4/compatibility.html

[2]

One entry in the 1.4 release notes says that the Windows look-and-feel has been updated to match better the Win95-2k look-and-feel, which closes bugid 4268204. This will change the presentation of pre-1.4 apps that use the default widget sizes provided by the Windows look-and-feel. I realize that floating widgets aren't really a big deal if one uses layout managers, but it's one example.

http://java.sun.com/j2se/1.4/docs/guide/swing/1.4/windows.html#bugs

[3]

Spec-trac appears to be the primary tool for enforcing backward compatibility in JRE implementations.

http://developer.java.sun.com/developer/technicalArticles/JCPtools/

[4]

JavaCheck indicates compatibility of an app with older JREs and various J2ME platform subsets, but I would hate for it to be used to test forward compatibility.

http://java.sun.com/products/personaljava/javacheck.html

[5]

Comments in bugid 4267080 suggest some complementary changes to client-side Java that could accompany this shared-VM migration.

http://developer.java.sun.com/developer/bugParade/bugs/4267080.html

walpj at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...
# 13

Hello,

I would like to workaround bug 4080029 :

http://developer.java.sun.com/developer/bugParade/bugs/4080029.html

"a modal dialog block input to all frame windows not just its parent" ....

Is there way to workaround this bug using SunToolkit.createNewAppContext() and AppContext ?

I imagine that if each different swing application is started in a different thread but in the same jvm, if each application has a distinct AppContext -> each application has a different awt-thread --> each modal dialog of an application would be modal only for its application.

Do you agree with that ?

Who has succeed to deal with bug 4080029 ?

Who knows how to use AppContext / SunToolkit ?

Thanks

Herbien

herbien at 2007-6-29 10:46:48 > top of Java-index,Other Topics,Java Community Process (JCP) Program...