I have two Java projects: one is a library, and the other is a console application. In the library project, I have an abstract class with a few static member variables (for global access). It looks a bit like this:
public abstract class AbstractHelper
{
public static final VarType someVar = new VarType();
}
I access the static member variables from the console application in two different classes.
For some reason, 'someVar' has unique instances across the two different classes that access it. If I access 'someVar' from an instance of Class A, I get a different object than when I access 'someVar' from an instance of Class B.
However, if I move AbstractHelper from the library project into my console application project, then it has the expected behavior (single instance of static member variable(s) shared across multiple classes)
Does anyone know why this happens?
This can happen by using different classloaders. OSGI, java-ee servers and several other technologies allow easy injection of different classloaders to the JVM.
You can resolve the problem: define both your library and your console application classes on the same classpath.
Related
Oracle JavaDocs explains that IllegalAccessError is
"Thrown if an application attempts to access or modify a field, or to
call a method that it does not have access to."
I try to load a class dynamically and I get this exception.
if I understand correctly when you use a classloader to load a class with a private package dynamically IllegalAccessError happens
the class I am trying to load is using
org.xml.sax.helpers.SecuritySupport
which also states in their description in the following url
http://grepcode.com/file/repository.springsource.com/org.apache.xmlcommons/com.springsource.org.apache.xmlcommons/1.3.4/org/xml/sax/helpers/SecuritySupport.java
that
Unfortunately, we can't load the class using reflection
* because the class is package private. And the class has
* to be package private so the APIs aren't exposed to other
* code that could use them to circumvent security. Thus,
* we accept the risk that the direct reference might fail
* on some JDK 1.1 JVMs, even though we would never execute
* this code in such a case. Sigh...
how can I dynamically load it anyway? I have to get it to work.
also if I get an error when I use a classloader, I cannot recover from that, so how can I know in advance that I cannot load this class?
thanks in advance to anyone who helps
The statement “we can't load the class using reflection because the class is package private” doesn’t make any sense, as can be shown easily:
package somepackage;
class BaseClass {
public static void main(String[] args) throws ReflectiveOperationException {
BaseClass obj=(BaseClass)
Class.forName("somepackage.SubClass").newInstance();
obj.aMethod();
}
void aMethod() {
System.out.println("base class");
}
}
class SubClass extends BaseClass {
#Override
void aMethod() {
System.out.println("method overridden by subclass");
}
}
This works flawlessly, printing method overridden by subclass replicated the actual use case of that SecuritySupport class.
However, since that class obviously serves the purpose of allowing a transition between Java 1.1 and Java 1.2, it might be possible that there were such restrictions twenty years ago, when this transition happened.
Your use case, however, is entirely different. You say that you are trying to load a class which “is using org.xml.sax.helpers.SecuritySupport”, which doesn’t imply that it is using said class via Reflection, but as shown above, that doesn’t matter anyway. It either case, it would only work, if the class is in the same package, whether you load the class “dynamically” or not.
There are only two possible scenarios.
If the class is truly within the same package, which at runtime implies that it also has been loaded by the same class loader, which would require that is also part of the JRE, if the JRE’s org.xml.sax.helpers package defines a SecuritySupport class, then the class can access the class within the same package.
If you are trying to load a class via a different ClassLoader from a different code source, it will not be of that package, even if you’d give it a qualified name of the org.xml.sax.helpers.SomeClass form. If the JRE’s org.xml.sax.helpers package happens to define a SecuritySupport class, all non-JRE classes would be in a different package. When it tries to access that class, which is not part of the official API, it doesn’t work.
Note that all standard class loaders follow a delegation model trying to resolve a name through their parent class loader first, which is the reason why they all would prefer the JRE’s org.xml.sax.helpers.SecuritySupport class, if there is one. With non-standard class loaders, you could have different, unrelated classes with that qualified name, being in different runtime packages.
In that second scenario, the question arises, why your class is using that class. In 2017, there’s rarely a need to differentiate between Java 1.1 and Java 1.2 and the functionality offered by that class is also only relevant for a class within the privileged code source of the JRE (or different code sources with different privileges in general).
I am developing two Android applications with similar -- but not identical -- logic, and I want to share code between them. Currently, I have a project for each application, and an additional project for shared classes. The shared-classes project is a library, and the application projects are linked to this library.
The problem I have is with a class that's responsible for getting data from the server and caching that data. The class is called DataSingleton. Fetching the data has some logic which is the same for both applications, and some which is different. My question is how to design the class to support this.
There are some limitations here:
The data Singleton should be a singleton, as implied by its name.
Some of the shared logic in the shared project uses the DataSingleton, so the DataSingleton must also be in the shared-classes project (otherwise I get a build error).
I don't want to put the application-specific logic in the shared project.
If this was C++, I would have 2 different classes name DataSingleton -- one in each application -- and then have the linker connect the correct class. Both classes could inherit from some common base class, to handle the code sharing for shared logic. Can I do something similar in Java?
If it helps, I can "initialize" the DataSingleton at the start of the application with some argument that will determine its behavior. I thought about passing a class to it, but then that class doesn't have access to the DataSingleton's private members.
What is the "right" way to do this?
Think about singleton. It is a class that does 3 thigs:
1. it has a business logic
2. it creates instance of itself
4. it holds this single instance and provides access to it.
You want to hold more than one implementations of your class. This means that you need interface and/or abstract base class and several concrete classes. But in this case the best solution is to separate #1 from #2 and #3: create hierarchy of DataFetchers (I am sorry, I changed your name DataSingleton because it does not describe the reality any more) and DataFetcherAccessor:
interface DataFetcher {}
class DataFetcher1 implements DataFetcher{}
class DataFetcher2 implements DataFetcher{}
class DataFetcherAccessor<A extends DataFetcher> {
private static A accessor;
public static void setImpl(Class<A> c) {
accessor = c.newInstance();
}
public static A getAccessor() [
return accessor;
}
}
There are obviously a lot of other solutions. For example you can use SPI to locate available implementation of your interface. You can also scan your classpath yourself and discover available implementation of interface DataFetcher or use Reflections for this.
Strip the DataSingleton in the shared project of the parts that will need to change in the different projects, define it as an abstract class and change its name to AbstractDataSingleton or something like that, then just create 2 separate classes in each product called DataSingleton or whatever and make them extend the AbstractDataSingleton in the shared project.
We have a Shared Utilities project, two independent SDK projects (each referring to the Utilities) and some plugin projects, each using only one of those SDKs. Shared Utilities contains some all-static classes, which need to be made visible to the plugins mentioned, but we'd like to hide the rest of its classes from them.
How we can go about resolving the issue? We'd like to keep the build process as simple as possible (we're using Ant for the build) with least possible dependencies.
Here's the options we've considered so far and why we've discarded each approach:
Second Shared Utilities project, which will be made available to the plugins - will make deployment harder.
Build 2 separate .jar-s from the Shared Utils project, one containing only the all-static utilities and the other - whatever needs to be hidden. This would make the build more complex, i.e. additional dependencies to the plugins' build scripts.
Proxy all-static classes in each of the SDKs - duplicate method definitions, but the implementation simply calls the corresponding static method from the Shared project - seems most painless, downside is we'd need to copy the Javadoc by hand. Is there a simple Javadoc tag, which would do this automatically upon generation?
Convert all-static classes to "normal" and simply create subclasses in each SDK - unnecessary (to my mind) performance overhead.
"Exposing static methods through proxy classes"
I've read your complete question and I'm not sure what is your issue exactly.
Exposing static (non-instance related) method through a proxy (instance).
What you wan't to hide from what exactly. What you want to expose to what exactly.
public class A {
private A(){} //prevent instanciation
public static void doSomething(){} //want to expose to some class, hide from other
}
To limit exposition of doSomething you can set the visibility: Controlling Access to Members of a Class.
You can also remove the static nature and use a static factory pattern to return the object like:
public class A {
private A(){}
public void doSomething(){} //want to expose to some class, hide from other
//the new A can also be set in a member variable and
//return always the same instance, if it is unmuttable it will be thread safe.
public static A getInstance(){ return new A();}
}
This can look like the "same thing" but you can now control the visibility of all method in A by controlling only the visibility of the getInstance(), the javadoc stay on A, now to control exactly how the getInstance can be access... I would have to understand exactly what you want to do.
When I access a singleton Java object from withing a servlet, that object is only "single" or "one instance" for the give servlet thread or single throughout the JVM on the Server OS (like Linux)?
I mean when client connects to the servlet/service, are singleton object are unique to each thread created for each client or its unique throughout the whole JVM installed in the machine?
I think the object is unique for each user, not to the whole JVM. The only persistent information is the one you put in the user session.
I'm not sure, but I think you can acomplish to have one instance of a Class in the whole Application Server using the ClassLoader class, however I don know how it's done.
UPDATE:
Taken from the Java Article "When is a Singleton not a Singleton?"
Multiple Singletons Simultaneously Loaded by Different Class Loaders
When two class loaders load a class, you actually have two copies of the class, and each one can have its own Singleton instance. That is particularly relevant in servlets running in certain servlet engines (iPlanet for example), where each servlet by default uses its own class loader. Two different servlets accessing a joint Singleton will, in fact, get two different objects.
Multiple class loaders occur more commonly than you might think. When browsers load classes from the network for use by applets, they use a separate class loader for each server address. Similarly, Jini and RMI systems may use a separate class loader for the different code bases from which they download class files. If your own system uses custom class loaders, all the same issues may arise.
If loaded by different class loaders, two classes with the same name, even the same package name, are treated as distinct -- even if, in fact, they are byte-for-byte the same class. The different class loaders represent different namespaces that distinguish classes (even though the classes' names are the same), so that the two MySingleton classes are in fact distinct. (See "Class Loaders as a Namespace Mechanism" in Resources.) Since two Singleton objects belong to two classes of the same name, it will appear at first glance that there are two Singleton objects of the same class.
I'd say it depends on how the singleton is implemented, but all requests for a given app execute in the same VM, so it should be one instance for all requests.
EDIT: This is assuming a straight-forward Singleton implementation similar to:
public class MySingleton {
private static MySingleton _instance;
// for sake of simplicity, I've left out handling of
// synchronization/multi-threading issues...
public static MySingleton getInstance() {
if (_instance == null) _instance = new MySingleton();
return _instance;
}
}
Yes it is Singleton. But the scope of the singleton depends on where the class is located.
If it is located inside application, it is singleton for that application. If the same class is present inside another application then another object is created for that application and it is singleton for that application.
If it is located outside application and within server, it is singleton for the VM.
According to this
https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html
every Web application has it's own class loader, so the singleton will be unique for one application and it can't be visible to another
When you create a Singleton instance, all request instances will share the same instance for the current class loader it uses.
Since all the Servlets run on a webserver which runs on a single JVM, there will be only a single Singelton Object for all your servlets.
Are Java static variables shared across instances of the same web application?
class MyClass
{
private static SomeClass myStaticObject = new SomeClass();
}
If a web application uses MyClass and multiple instances of that application is run on a web server, is myStaticObject initialized multiple times?
Typically, yes. Most containers will provide separate classloaders for each web application. This will result in the class being loaded multiple times when used by several applications, and thus resulting in multiple instances of the static variable.
Stating the Java Language Specification for reference:
At run time, several reference types
with the same binary name may be
loaded simultaneously by different
class loaders. These types may or may
not represent the same type
declaration. Even if two such types do
represent the same type declaration,
they are considered distinct.
By inference, multiple instances of static variables will exist, unless the classes are loaded only once by a parent class loader, and never loaded elsewhere by any other class loader.
I don't quite see the point of having a private static variable in MyClass. If it's private you cannot access it as a class variable from outside the class you defined it in. If you just want other classes to access this variable via a getter method you should remove the static keyword.