92

In Java the private access modifier consider as safe since it is not visible outside of the class. Then outside world doesn't know about that method either.

But I thought Java reflection can use to break this rule. Consider following case:

public class ProtectedPrivacy{

  private String getInfo(){
     return "confidential"; 
  }

}  

Now from another class I am going to get Info:

public class BreakPrivacy{

   public static void main(String[] args) throws Exception {
       ProtectedPrivacy protectedPrivacy = new ProtectedPrivacy();
       Method method = protectedPrivacy.getClass().getDeclaredMethod("getInfo", null);
       method.setAccessible(true);
       Object result = method.invoke(protectedPrivacy);
       System.out.println(result.toString());
   }
} 

At this moment I just thought still private method safe since to do some thing like above we must know method name. But if class which contain private method written by some one else we don't have visibility of those.

But my point become invalid since below line of code.

Method method[] = new ProtectedPrivacy().getClass().getDeclaredMethods();

Now this method[] contains all the things need to do above thing. My question is, is there a way to avoid this kind of things doing using Java reflection?

I am quote some point from Java Documentation to clarify my question.

Tips on Choosing an Access Level:

If other programmers use your class, you want to ensure that errors from misuse cannot happen. Access levels can help you do this.Use the most restrictive access level that makes sense for a particular member. Use private unless you have a good reason not to.

Roman C
  • 49,761
  • 33
  • 66
  • 176
Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115
  • 1
    Using an obfuscator may help, because `getDeclaredMethods` would return names that look like garbage. – Sergey Kalinichenko Nov 08 '13 at 10:28
  • 214
    Private, protected public etc is not for security, it is to avoid well meaning people from making mistakes. Do not use it as a security measure – Richard Tingle Nov 08 '13 at 11:10
  • 20
    Java code is decompilable anyway. An 'attacker' could just download a Java decompiler and read your code, or change 'private' to 'public'. – 11684 Nov 08 '13 at 11:16
  • 7
    To elaborate what @RichardTingle commented (+1 btw). There is a great and important difference between security and safety. Where the latter is the problem mitigated with access modifiers; to not break things _by accident_ – user Nov 08 '13 at 13:10
  • 3
    All this is pretty clear to programmers where access modifiers do not exist, like in Python. In these languages private/public are simply distinguished by a convention in the names (in python anything that starts with a single underscore should be considered private). This makes it pretty clear that marking something as "private" does *not* add any security, but it's only a simple way of saying what people *should* use of your API. I have my doubts that having a compiler check for this things helps at all since it's damn easy to follow the convention without "external" help. – Bakuriu Nov 09 '13 at 09:59
  • Dependency injection systems and ORM libraries often use reflection to bypass `private`. The `private` modifier then becomes *"Programmers do not need and should not want to know about this. System services might, but programmers should only configure them to interact with them."* Suppose you are trying to use *get-less* programming, using `Name.appendFullName(Appendable)` instead of `Name.getGivenName()` and `Name.getSurName()`. You can still use Hibernate to get `Name` objects from a database. – Eric Jablow Nov 12 '13 at 22:53
  • may be the link help you http://stackoverflow.com/questions/7566626/how-to-restrict-developers-to-use-reflection-to-access-private-methods-and-const?rq=1 – Nikesh Pathak Nov 13 '13 at 04:31
  • Your question really seams to be, "how do I stop reflection from accessing my private parts"? You might consider rephrasing it, unless you had a different intent. – Glenn Teitelbaum Nov 15 '13 at 00:05

7 Answers7

95

It depends on what you mean by "safe". If you're running with a security manager that allows this sort of thing, then yes, you can do all kinds of nasty things with reflection. But then in that kind of environment the library can probably just be modified to make the method public anyway.

Access control is effectively "advisory" in an environment like that - you're effectively trusting the code to play nicely. If you don't trust the code you're running, you should use a more restrictive security manager.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    Tangential, I know, but could you elaborate just a bit on what a more restrictive manager would be in this sense? – Gray Nov 08 '13 at 16:59
  • 12
    @Gray: An instance of [SecurityManager](http://docs.oracle.com/javase/7/docs/api/java/lang/SecurityManager.html) which throws exceptions on the relevant `check*` calls, basically. – Jon Skeet Nov 08 '13 at 17:07
40

Access modifiers have nothing to do with security. In fact you can and should look at access modifiers as the reverse of security -- it is not to protect your data or algorithims, it is to protect people from the requirement to know about your data and algorithims. This is why the default modifier is package -- if they are working on the package they probably already need to know.

Along with the knowledge of the data and the methods of your code, comes the responibility to know when and how to use it. You don't put private on your inIt method to keep someone from finding out about it, you do so because (a) they aren't going to know that you only call that after foo and only if bar = 3.1415 and (b) because it does them no good to know about it.

Access modifers can be summed up in a simple phrase "TMI, dude, I so didn't need to know that".

jmoreno
  • 12,752
  • 4
  • 60
  • 91
  • 3
    Great answer, but I did need to google to find out that TMI meant Too Much Information. I guess I need to spend more time in the valley :-) – mikelong Nov 15 '13 at 15:02
7

By saying 'safe', you are protecting you or other developers, which are using your API to not harm the object by calling your private method. But if you or they really need to call this method, they can do it with Reflection.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
Arsen Alexanyan
  • 3,061
  • 5
  • 25
  • 45
6

The question is who are you trying to save it from. In my opinion, such a client of your code is the one at a loss here.

Any piece of code (written by you or others) which tries to access a private member of the above class is essentially digging its own grave. private members don't make a part of the public API and are subject to change without notice. If a client happens to consume one of such private members in the manner given above, it's going to break if it upgrades to a newer version of the API in which the private member got modified.

5

With facility, there comes responsibility. There are thing's you can't do, & things you can do but you shouldn't do.

Private modifier is provided/used as/in the most restricted manner. Members which should not be visible outside the class shall be defined as private. But this can be broken with Reflection as we see. But this does not mean that you should not use private - or they are unsafe. It is about you shall use things judiciously or in constructive manner (like reflection).

Raúl
  • 1,542
  • 4
  • 24
  • 37
5

Assuming you trust the client programmer of your API, another way of looking at is how 'safe' it is for them to use those particular functions.

Your publicly available functions should provide a clear, well-documented, rarely-changing interface into your code. Your private functions can be considered an implementation detail and may change over time, so are not safe to use directly.

If a client programmer goes out of their way to circumvent these abstractions, they are in a way declaring that they know what they are doing. More importantly, they understand that it is unsupported and may stop working with future versions of your code.

robbie_c
  • 2,428
  • 1
  • 19
  • 28
5

private is not for security, it is to keep the code clean and to prevent mistakes. It allows users to modularize the code (and how it is developed) without having to worry about all the details of the other modules

Once you release your code, people can figure out how it works. There's no way to "hide" the logic if you eventually want the code to run on a computer. Even compiling to binary is jsut a level of obfuscation.

So, there's no way that you can set up your API to do special things that you don't want others to be able to call. In the case of a web API, you could put the methods you want control over on the server side.

Manishearth
  • 14,882
  • 8
  • 59
  • 76