Isolating a static singleton class using class loaders

custom class loader java
java class loader
static class loading and dynamic class loading
java replace class at runtime
context class loader
security class loaders in java
primordial class loader
what is a class loader can you have more than one class loader

Disclaimer: This is probably not the best solution given the issue, but I'm curious how this implementation could be achieved.

Problem I'm trying to deal with some legacy code which has a singleton defined like bellow:

public class LegacySingleton {
    private static Boolean value;

    public static void setup(boolean v) {
        if (value != null) {
            throw new RuntimeException("Already Set up");
        }
        value = v;
        System.out.println("Setup complete");
    }

    public static void teardown() {
        value = null;
        System.out.println("Teardown complete");
    }

    public static boolean getValue() {
        return value;
    }
}

I do not have the ability to change this design and the class is used heavily throughout the code base. The values returned by this singleton can greatly change the functionality of the code. Eg:

public class LegacyRequestHandler {
    public void handleRequest() {
        if (LegacySingleton.getValue()) {
            System.out.println("Path A");
        } else {
            System.out.println("Path B");
        }
    }
}

Right now if I want the code to take Path A, then I have to initialize LegacySingleton in a particular way. If I then want to take Path B I have to re-initialize the LegacySingleton. There is no way of handling requests in parallel which take different paths; meaning for each different configuration of LegacySingleton required I need to launch a separate JVM instance.


My Question Is it possible to isolate this singleton using separate class loaders? I've been playing around with the ClassLoader API, but I cant quite figure it out.

I'm imagining it would look something along the lines of this:

public class LegacyRequestHandlerProvider extends Supplier<LegacyRequestHandler> {
    private final boolean value;
    public LegacyRequestHandlerProvider(boolean value) {
        this.value = value;
    }
    @Override
    public LegacyRequestHandler get() {
        LegacySingleton.setup(value);
        return new LegacyRequestHandler();
    }
}

...

ClassLoader loader1 = new SomeFunkyClassLoaderMagic();
Supplier<LegacyRequestHandler> supplier1 = loader1
    .loadClass("com.project.LegacyRequestHandlerProvider")
    .getConstructor(Boolean.TYPE)
    .newInstance(true);

ClassLoader loader2 = new SomeFunkyClassLoaderMagic();
Supplier<LegacyRequestHandler> supplier2 = loader2
    .loadClass("com.project.LegacyRequestHandlerProvider")
    .getConstructor(Boolean.TYPE)
    .newInstance(false);

LegacyRequestHandler handler1 = supplier1.get();
LegacyRequestHandler handler2 = supplier2.get();

Another Java Singleton Problem, This started me thinking about how the singleton pattern would behave. Rather than storing a static reference to the current instance, the singleton class can If your applet can instantiate a ClassLoader and load its classes from that, you can described at the top) which if used correctly will isolate one user from another. Both static class and singleton class can have only one instance of a copy that is available in memory throughout the whole application. They both are used for holding the global state of an application. Both static classes and singleton classes can be implemented as thread-safe.

/First, tell your lead that you are about spend time and make convoluted code that uses more memory and could be slower due to jit re-compilation and other class init issues, because you are somehow not allowed to fix bad obsolete code. Time and maintainability is money./

Ok, now... Your funky classloaders are just URL classloaders with the required jars given. But the trick is to NOT have the singleton nor the handlers in the main classpath, otherise the classloader will find the class in a parentclassloader (that has precedence) and it will still be a singleton. You knew that I'm sure.

Another radical solution is to re-implement the offending class your way (with properties file, or with a Threadlocal field (assuming the work is done on same thread) that a caller can set before making the call to the handler, which in turn will not see the mascarade).

You would have to deploy your overriding class with precedence in the classpath (list the jar earlier), or for a webapp, if you can, deploy in the web-inf/classes which overrides anything in the web-inf/lib. You can ultimately just delete the class from the legacy jar. The point is to have the same classname, same methods signature, but a new implementation (again, that relies on loading cfg files or using threadlocal setup before the call).

Hope this helps.

How to Use Java Classloaders, The Java bootstrap class loader is used heavily by Java EE containers, OSGi be loading Counter in an isolated classloader, so Main cannot use it directly Static fields commonly hold caches, singleton objects, and various  For singleton classes, we create an instance using its static property and at any time it creates a single instance of a class. You should have checked in the above example that even when you try to create multiple instances of a singleton class, it returns the same instance as was created the first time.

In my view –and my apologies that this is a largely opinion-based answer– this is a business problem and not a technical problem, because the constraints given ("I cannot change the code") are not technical ones. But as anybody working in software development can attest, business constraints are part and parcel of our jobs.

Your issue can be abstracted as follows: "Considering constraint A, can I get result B?" And the answer is: "No, you cannot." Or perhaps you can, but with a solution that is difficult –in other words, expensive– to maintain and prone to break.

In cases like these, it would be good to know why you cannot change the software that has obvious and very serious design problems. Because that is the real problem.

Java Class Reloading Tutorial for Advanced Developers, Example 1: Reloading a Class with Java Class Loader we were to use the default class loader again ( with the command StaticInt.class. Because it's very important to understand how we isolate the persisted space and reloadable space,  Fourth version - not quite as lazy, but thread-safe without using locks public sealed class Singleton { private static readonly Singleton instance = new Singleton(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Singleton() { } private Singleton() { } public static Singleton Instance { get

Singleton Pattern Pitfalls, public class Singleton { private static Singleton instance = new The problem is that you cannot completely isolate classes dependent on singletons. The problem is when using multiple classloaders or deploying the app to  Static class. You can make a static class with the static keyword. In the example, look at how the static keyword is used on the class and constructor. Static classes may be simpler, but the singleton example has many important advantages.Static. Differences: There are important differences between the singleton design pattern and the static

How ClassLoader Works in Java?, Class Loader is a component with the Java Execution Engine which loads the Binary data from The initial class is loaded with the help of public static main() method declared in your class. runtime; Use different versions of an API library (e.g. an XML parser) in parallel; Isolate different What is singleton class in Java​? 5 Answers 5. Your second code snippet is, in my opinion, the best way of thread-safe lazily initializing a singleton. I would suggest you use it. Replying on the class loading behavior of the JVM rather than making your laziness explicit sounds to me like a bad idea.

Singletons And Shared Instances, The Singleton is a software design pattern that has been described in the book above hierarchy would be properly isolated from the rest, without the developers The basic principle is that you have a static mapping of the interface, and If you omit loading the plugins, you risk returning the wrong data. You need to define the static member variable instance.Somewhere in global scope (for example between the class and the main function) add the following line:. singleton *singleton::instance = 0; // use 'nullptr' if your compiler support it

Comments
  • You'd have to isolate/duplicate whole class hierarchies in their own classloaders, and before you even go down that way there are plenty of easier possibilities to look at. But for us to consider those possibilities you'll have to explain what that class does, how it's used, and what your root problem is (not how you thought about solving it).
  • @Kayaman Root of the problem is that the legacy code base doesn't provide a good way of inject configurations. They're strongly tied to the classes because of the singleton pattern. Without a major rewrite of the code base there's no real way to allow multiple configurations for many classes. This is probably not the best solution, but I'm curious what this solution would require (as an educational exercise at this point). My best option in reality is probably containerizing the application/environment and running several instances of the application.
  • It wouldn't be enough to load just the singleton class dynamically. You'd have to load the hierarchy, which would result in something like containerization. But that would probably be taking the hard way. Hard to say without knowing the specifics.
  • @Kayaman I see; that makes sense. One advantage I was curious of were potential savings in program memory by not having to launch a multiple JVM instances. But if I have to reload everything in the classpath then I probably don't save much of anything, and end up increasing the complexity of the application a lot. That said; I am still curious what this implementation would look like. I couldn't find any example to run off of, but I may just not know the right buzzwords to search for.
  • You need to show us how you make a decision that the flow show take Path A or B and also how the request is being handled, what framework is used?