6

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

Jijoy
  • 12,386
  • 14
  • 41
  • 48

7 Answers7

6

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.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
Maurice Perry
  • 32,610
  • 9
  • 70
  • 97
1

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
  • 342,105
  • 78
  • 482
  • 720
0

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 Adam
  • 161,610
  • 92
  • 305
  • 395
0

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.

Timothy
  • 2,457
  • 19
  • 15
0

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
  • 18,240
  • 8
  • 37
  • 52
0

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
  • 14,900
  • 6
  • 36
  • 74
  • 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). – whiskeysierra Apr 17 '10 at 17:27