So I have a fairly complex applet structure from a couple years back, and I have a question about a global class that is in it. Basically, I have three applets on the same page and they interact with each other in different ways. The part I'm confused about is the fact that they all share global (static) variables from the same class. How exactly is this happening? I was under the impression that each applet would have its own little environment and would thus be unable to access the same static variables as the others? For example if I have this in applet A:
Globals.globalVar = 5;
And this in applet B:
int x = Globals.globalVar;
And I ensure that B starts AFTER A then x will become 5. I would like to know how exactly this is handled in the JVM, as it doesn't quite make any sense to me. Does this behaviour imply that if you have two separate java applications running at the same time they can access each others static variables? Thanks beforehand.
Because that's how it's defined, for backward-compatibility reasons. See http://download.oracle.com/javase/6/docs/technotes/guides/jweb/applet/applet_execution.html#cache:
Normally, if two applets have the same codebase and archive
parameters, they will be loaded by the same class loader instance.
This behavior is required for backward compatibility, and is relied on
by several real-world applications. The result is that multiple
applets on the same web page may access each others' static variables
at the Java language level, effectively allowing the multiple applets
to be written as though they comprised a single application.
While this feature enables certain kinds of applications to be
conveniently written, it has certain drawbacks. It interferes with
termination of applets, in particular when multiple instances of the
same applet are active. It makes the programming model for applets
more complex, since it is under specified exactly when the static
fields of an applet will be re-initialized, and when they will be
maintained from run to run of the same applet. It causes imprecise
behavior of certain user interface operations within the Java Plug-in
due to the inability to identify exactly which applet initiated a
particular request.
For this reason, the new Java Plug-in provides a way to opt out of the
use of the classloader cache on an applet by applet basis.
Related
I have a piece of hardware for which I already have written a small library to provide controls. Previously I used CLI with the program to control the hardware, but now I want to give multiple users access over the network. The control is handled via an object instance, in short, this is non-static and it can't be static as there are runtime configurations as well as important hardware state information to store, but I want to provide control of this hardware to connected sessions. The way I previously had this work was by having my main function set in my serverEndpoint class, and it handled the runtime configuration of the object. This design is messy, and I'd prefer to not organize the code this way, but I've not found any good guides for this elsewhere and I question if perhaps I'm just an atypical use-case or if websockets are the wrong approach, though logically I can't see why that would be. Anyway, my question is how should I provide a handle to this instance to sessions? The hardware control class is already configured to be threadsafe.
Alernatively, my real impetus for reorganizing the code was so that it would be more easily testable, which isn't really possible with the main function located inside the serverEndpoint as far as I'm aware.
By definition, there can be a single instance of a Java singleton class. Except of course when there's obviously several, including the same code running on different physical machines, virtual machines, Java Virtual Machines.
Is the insurance that a JVM has a single instance of a singleton class?
In what domain is a Java singleton class unique? What relation to the notion of application, whatever the meaning of that is? What relation to the notion of process or thread in the operating system hosting the JVM? Of user connection in a web server? Does it change if we are talking Apache or Tomcat?
I design a Java class to be supplied to other software developers, which will access a remote functionality through it. That functionality is implemented redundantly on several distant machines. The class keeps a list of these machines, tracks their response time, and makes sure the requests received from its callers are sent to the currently most responsive distant machine. That's a good use case for a singleton.
I have only a vague idea of what the other developers will call my class from. I know that's going to be a web server, accessed by end users. I know the other software developer's code is written in Java (because the code I replace is C and called from JNI). They talk about calling my code from several apps they make on the same machine, but I do not know what exactly that means. Definitely some run their web server on Tomcat with multiple apps in the same server. Another apparently lean towards Apache Web Server, and yet another mentioned NGINX. The less I know about what they do, the better.
I know my code will run in relatively few JVMs instances on the same machine (as shown by top), and I can live happy with that few instances of my singleton. It would be a serious issue if there was 1 singleton per end user of the web server, a mild issue is there was one per "app". I'd like to know at the design phase, rather than discover in the field.
Usually the class loader loads only a single instance of each class into memory. So all static variables exist only once per Java VM.
But in web applications (e.g. on Apache Tomcat or similar) it's a bit different because each application has its own class loader and there is another class loader for shared libraries.
When your Tomcat runs two applications which contain the same library (inside the *.war), you have effectively two instances of the same library in memory, so their static variables exist twice. But when two applications share a library from the lib folder, then you have only one instance in memory.
However, by implementing a custom class loader, you can alter that behavior and then it's up to you.
Thread do not affect this normally unless you write your own class loader with specific features for threads.
GlassFish allows creating N domains. Every domain has its own Java classes (libraries etc) and system settings.
For example, we have two domains - domain1 and domain2.
Via GF web console (http://localhost:4848) one system property was set for domain1 - com.temp.foo=test1. Besides via GF web console (http://localhost:7575) one system property was set for domain2 - com.temp.foo=test2.
Now, in domain1
System.out.println(System.getProperty("org.temp.foo"))
//returns `test1`
And in domain2
System.out.println(System.getProperty("org.temp.foo"))
//returns `test2`
As I understand GF and all its domains are running in one instance of JVM. And I don't understand how it is possible in one instance of JVM separate system properties. Could anyone explain?
Note: I understand that it can be a very long explanation that's why I am asking only about main principle and solutions/libraries names in an order I could read about them on the internet.
It seems that the understanding "GF and all its domains are running in one instance of JVM" is wrong.
As per GlassFish current version's documentation (chapter 3):
A domain contains a group of GlassFish Server instances that are administered
together. [...] A GlassFish Server instance is a single Virtual Machine for the Java platform (Java
Virtual Machine or JVM machine) on a single node in which GlassFish Server is
running.
That means, every single instance of any domain is running in its own JVM! As a consequence, they all could have their own different system properties.
To be fair: There are means for administering virtual servers in GlassFish, that seem to share a JVM, but I think you are not speaking about them.
Products such as GlassFish, JBoss, WebSphere, ... "simply" make use of the Java class loading mechanism to create isolation. By using multiple class loaders, even a static class fields could exist "more than once"; and each "domain" gets its very special version of that.
Start reading here, or there for example:
Application Universe – Each Java EE application has its own class loader universe, which loads the classes in all the modules in the application.
And beyond that, look into this.
In other words: although the System class obviously represents a "system view" - the class loading mechanism should make it possible to give different System class instances to each domain. Thereby making it possible to have domain-specific properties within each domain-specific System class. But to be precise: I could not find clear evidence to back up this statement. On that topic, here and there should help (the later one indicating that there even ways to tamper with the system classloader).
But thinking further, there is a problem with that idea: there are actually two class loading mechanisms. There "system/user" class loaders ... and the initial bootstrap classloader.
And the bootstrap classloader is actually "baked" into the JVM (it is implemented in native code for example) - and it can't be replaced.
And java.lang.System should be loaded by that bootstrap classloader!
So it is impossible to use "classloader magic" to enable "per domain" System properties!
The other option I see is to create a Java agent that intercepts calls and manipulates their result (see here as starting point).
But again; agents come "after" bootstrapping has completed!
So the only logical conclusion (taking what is left after excluding all options): the premise of the question must be wrong!
It is simply impossible that different "applications" running on the same JVM give different system properties. And luckily, the great answer by Seelenvirtuose confirms that conclusion.
All,
I'm working on the design of a cloud-based service that will provide the option to execute some "plugin" code submitted by clients. In order to make this work it is essential that the plugins can't threaten system integrity or have any ability to access the data of other clients.
Ideally I'd like it to be possible for clients to submit a simple jar file (containing a class conforming to some pre-defined interface) which would then be run within a sandbox.
The client code should be allowed to:
Take as much CPU time as it needs on a single thread
Perform any calculations using standard java classes (e.g. java.lang.Math, java.util.Random etc.)
Call any libraries bundled in the jar (but which must be subject to the same restrictions)
But I would specifically need to disallow the following:
Spawning new threads (so that server resource can be fairly managed!)
Any access to the file system / IO / network
Any access to native code
Any access to data in the JVM other than that passed to / created by the client code
Any access to reflection on classes other than those in the .jar sandbox
Any ability to call methods on objects outside the sandbox, other than the standard Java libraries
Is it be possible to achieve this with a custom ClassLoader / SecurityManager setup? Or will I need to start looking for a more sophisticated solution (e.g. launching multiple JVMs?)
Managing resource and limiting resources is not possible in java. You can prevent malicious code to access system resources (disk/network and so) or the JVM itself but:
...
Spawning new threads (so that server resource can be fairly managed!)
If i wanna be malicious I am gonna do all my code in the finalizer thread and just block the VM. Same doing protected void finalize(synchronized(Thread.class) {for(;;) LockSupport.park();}} bye-bye new threads.
Eating all the memory, eating all direct memory and so on.
Accessing zip files in my own jar, and expect 'em getting moved away, so the JVM crashes (due to bug(s) in zlib)
If one purposely wants to deny resources, it is just not a feasible task to try and catch the hacker. You'd need to know what to search for and dynamically check/enhance the classes on run-time to disallow the behavior.
Any ability to call methods on objects outside the sandbox, other than the standard Java libraries
What are the standard libraries? Do you know if/when they must possibly execute some code in a privileged method.
Each customer - separate VM w/ full restrictions, process affinity/priority, incl max memory/stack and so on.
I think everything you want to achieve can be done through a custom SecurityManager. In fact it's pretty simple, you just create a class that extends SecurityManager, implement the two checkPermission(..) methods and in the first iteration just throw an SecurityException for everything that comes in (and log what you just denied). Then you allow specific operations until you find yourself in the situation that it's possible to create useful plugins and let your clients play with it. They will complain. Then you have to judge whether to allow them to do whatever they requested or if you want to stick with your rules. Here the difficult part begins...
I made up an applet to auto dial a contacts number via our phone system switchvox, as well as log the call information into our CRM, salesforce. The issue I am running into is that unless I use the separate JVM parameter things get screwy.
For example say they have multiple tabs open for multiple contacts, thus multiple applets running in the same jvm. Without the separate jvm parameter sometimes it will dial a number from another tab. I pass the number via the parameter tags and I have even tried passing the number by calling a JS method from the applet with still no luck.
Since our crm is cloud based people like to have multiple tabs open, but do not like seeing multiple java icons down below, go figure. Anybody have this issue before, and/or have a workaround without the separate jvms.
It is hard to say without looking at your applet's code.
But I would hazard a guess that your code is putting some of its mutable state in statics, and occasionally one instance of the applet is interfering with another via the statics.
If you have any shared mutable statics in your applet, ideally you should get rid of them. Or if the state really needs to be shared by multiple instances of the applet, make sure that all accesses are properly synchronized.
Statics are shared among the applets since they're all running in the same VM. You could try the classloader_cache="false" applet option and still share the VM. I am not sure whether this option applies only on applet startup, however, as I haven't had success with it working all the time.
The best bet is to get rid of statics or use separate_jvm.