views:

79

answers:

7

Hi , Assume I have a singleton class in an external lib to my application. But still I can create instances of that particular class using reflection. Like this

    Class clas = Class.forName(Private.class.getName());

    for(Constructor c : clas.getDeclaredConstructors()){
        c.setAccessible(true);
        Private p = (Private) c.newInstance();
        System.out.println(p);
    }

How can I restrict this ? .

Thanks J

+5  A: 

By using a SecurityManager and controlling controlling ReflectPermission("suppressAccessChecks") (example).

The security manager impacts performances though, and it is rarely used on the server side.

Maurice Perry
A: 

Long story short: you can't.

Any constructor, public as well as private, can be accessed by reflection and can be used to instantiate a new object.

You will need to resort to other methods such as SecurityManager.

Yuval A
A: 

I don't think that you can restrict this.

It is obviously a dangerous/questionable practice to use reflection to access the private parts of others (snicker), but it is sometimes necessary by various types of tools and applications.

Tim Drisdelle
+1  A: 

If you're talking about singletons in particular: that's one reason why the best way to implement them is via an enum:

public enum YourSingleton {
    INSTANCE;
    // methods go here
} 

If you're talking about using setAccessible() in general: If the code is written by someone you don't trust not to do underhanded tricks like that, you shouldn't run it anyway (or run it in a sandbox). Among developers, public/private should be considered metainformation about how the code is intended to be used - not as a security feature.

Michael Borgwardt
A: 

AFAIK this is sort of metaprogramming and therefore requires check on different layer of abstraction. From Javadoc I suppose, you should use SecurityManager to enforce the behaviour you want: setAccessible(). Generally IMHO you should really know what you are doing when you are metaprogramming and changing access should really have good reasons to be done.

Gabriel Ščerbák
A: 

You can do like this.

private static final Private INSTANCE = new Private();
    private Private() {
        if(INSTANCE !=null)
            throw new IllegalStateException("Already instantiated");
    }
     public static Private getInstance() {
            return INSTANCE;
        }
Vivart
The singleton is outside of his reach in a third party jar. So this won't help at all. This technique is by the way not safe, as you can change it via reflection (as mentioned in the question).
Willi