Is there a standard way in Java to mark classes, methods etc. that are used by other parts of the program in indirect ways (think: reflection) which are not discoverable by the usual search-functions of IDEs?
In one particular example I have a bunch of classes with a couple of hundred small validation methods. Validation occurs basically by listing all methods of those classes via reflection and executing one by one them on the given object. (It's more complicated than that, but that's the underlying idea)
Now my IDE understandably marks each and everyone of those methods as "unused" because there are never directly called, only via reflection.
A similar problem occurs in another part of the program where several dozen helper classes reside, some of which are almost certainly unused and could be deleted. But: In some rare cases the fields of these classes are accessed via reflection and the usual search functions of the IDE cannot find these usages (again: very understandably so).
I know that it is impossible for the IDE to solve this problem without outside help. Hence my question whether there are already established ways like annotations for example to clearly mark these cases. Of course I could define such an annotation myself, but I'd rather go with an accepted standard if one exists.
Is there even an IDE that can recognise them and warn me automatically if I'm doing stuff like that?
No, there is not a standard way to mark indirect control flow (reflection, Android intents, callbacks, etc.).
There are some tools that provide their own ways to analyze indirect control flow.
For example, the Checker Framework's reflection resolution uses the #MethodVal annotation to indicate the possible targets of a reflective invocation. It also has ways to indicate Android intents.
You typically annotate those classes with #SuppressWarnings("unused") to get rid of IDE warnings
Related
I am working on an API for a software so my users can extend it without modifying the source code. But, I want only certain functions to be accessed by certain classes for security reasons. Is there anyway to do this? Also, I have no code because I have no idea on how to do this.
Thanks! -Trent
I have two thoughts on this, one is that you can look at how Minecraft Forge created their plugin API.
Another way is to have a limited API between your core code and the actual plugins, but, you need to be careful of the platform. For example, if you write the core application in Java or C#, then I can use Aspect Oriented Programming (AOP) to bypass your security and have my code change the behavior of yours.
If you use functional programming (FP) languages, then you can protect more from this type of approach, if you also are not using languages on these platforms, but they are not perfect.
So, there is a trade-off between power and convenience, so how useful do you want your application to be, and how secure?
One possible solution that may work is if you go with something similar to Minecraft, though I doubt they do this, but, give a stub application to the user. They can extend it with plugins, and the interface functions they can modify are in the stub. When the program starts, the plugins are loaded, and the interface may be modified or extended, but, then the core program is pulled down and put into the stub, and then the actual program runs. The core program can be recompiled and manipulated so method names are changed, so reflection is harder to use, but taking this approach, and doing it well, would be hard.
BTW, I like Alex T's response, I just gave different terms to some of his, such as AOP instead of reflection and immutability is part of FP.
You mention jar, which means you are using something that runs on a JVM, so you may want to read up on AspectJ, as it can significantly alter the behavior of applications. You can have private methods, but I can put code that runs instead of yours, or change the parameters or the return value before or after the method is called.
To protect variables inside of classes, you can make them private, and accessible via getter and setter methods with varying levels of protection. This also applies to classes themselves; if you wanted to prevent the user from being able to instantiate a class, you could mark the class' constructor as protected to allow instantiation only within it's package.
If you wanted to hide the implementation details of a class altogether, you could declare the class as class X instead of public class X, which would hide methods from the API for standard development.
This will quickly get you the behaviour you're after, but there's an aspect of Java called reflection, which allows an executable Java program to analyze and manipulate it's own implementation; in this regard, no field or method is ever completely safe.
You can also safeguard variables by providing access to them via 'immutable' Objects; these are objects designed to forbid the caller from modifying the original source contents.
I want to redefine the bytecode of the StackOverflowError constructor so I have a "hook" for when a stack overflow occurs. All I want to do is insert a single method call to a static method of my choosing at the start of the constructor. Is it possible to do this?
You should be able to do it using one of two ways (unless something changed in the last 1-2 years, in which case I'd love some links to changelogs/docs):
Mentioned in a comment, not very feasible I guess, modify the classes you are interested in, put them in a jar and then use the -bootclasspath option to load them instead of the default ones. As was mentioned before this can have some legal issues (and is a pain to do in general).
You should be able to (or at least you used to be able to) instrument almost all core classes (iirc Class was the only exception I've seen). One of many problems you might have is the fact that many of core classes are being initialized before the agents you provide (or well their premain methods to be exact) are consulted. To overcome this you will have to add Can-Retransform-Classes property to your agent jar and then re-transform the classes you are interested in. Be aware that re-transformation is a bit less powerful and doesn't give you all the options you'd have normally with instrumentation, you can read more about it in the doc.
I am assuming you know how to do instrumentation?
There are several things to consider.
It is possible to redefine java.lang.StackOverflowError. I tried it successfully on 1.7.0_40. isModifiableClass(java.lang.StackOverflowError.class) return true and I successfully redefined it inserting a method invocation into all of its constructors
You should be aware that when you insert a method call into a class via Instrumentation you still have to obey the visibility imposed by the ClassLoader relationships. Since StackOverflowError is loaded by the bootstrap loader it can only invoke methods of classes loaded by the bootstrap loader. You would have to add the target method’s class(es) to the bootstrap loader
This works if the application’s code throws a StackOverflowError manually. However, when a real stackoverflow occurs, the last thing the JVM will do is to invoke additional methods (keep in mind what the error says, the stack is full). Consequently it creates an instance of StackOverflowError without calling its constructor (a JVM can do that). So your instrumentation is pointless in this situation.
As already pointed out by others, a “Pure Java Application” must not rely on modified JRE classes. It is only valid to use Instrumentation as add-on, i.e. development or JVM management tool. You should keep in mind that the fact that Oracle’s JVM 1.7.0_40 supports the redefinition of StackOverflowError does not imply that other versions or other JVMs do as well.
We have huge codebase and some classes are often used via reflection all over the code. We can safely remove classes and compiler is happy, but some of them are used dynamically using reflection so I can't locate them otherwise than searching strings ...
Is there some reflection explorer for Java code?
No simple tool to do this. However you can use code coverage instead. What this does is give you a report of all the line of code executed. This can be even more useful in either improving test code or removing dead code.
Reflections is by definition very dynamic and you have to run the right code to see what it would do. i.e. you have to have reasonable tests. You can add logging to everything Reflection does if you can access this code, or perhaps you can use instrumentation of these libraries (or change them directly)
I suggest, using appropriately licensed source for your JRE, modifying the reflection classes to log when classes are used by reflection (use a map/WeakHashMap to ignore duplicates). Your modified system classes can replace those in rt.jar with -Xbootclasspath/p: on the command line (on Oracle "Sun" JRE, others will presumably have something similar). Run your program and tests and see what comes up.
(Possibly you might have to hack around issues with class loading order in the system classes.)
I doubt any such utility is readily available, but I could be wrong.
This is quite complex, considering that dynamically loaded classes (via reflection) can themselves load other classes dynamically and that the names of loaded classes may come from variables or some runtime input.
Your codebase probably does neither of these. If this a one time effort searching strings might be a good option. Or you look for calls to reflection methods.
As the other posters have mentioned, this cannot be done with static analysis due to the dynamic nature of Reflection. If you are using Eclipse, you might find this coverage tool to be useful, and it's very easy to work with. It's called EclEmma
Suppose I have a class in my package org.jake and it has a method with default access (no modifier). Then the method is visible inside the package only.
However, when someone receives the jar of my framework, what is to stop them from writing a new class, declaring its package as org.jake, and using my supposedly invisible method?
In other words, is there anything I can do to prevent this?
You could seal the package in your jar file. It's not bullet-proof though.
The main thing is not to rely on access modifiers etc from a security point of view to start with, really. If someone is running the code with unrestricted permissions, they're going to have access to all kinds of things. Access modifiers really just help to stop people from accidentally shooting themselves in the foot.
If someone is willing to put classes in your package to circumvent your encapsulation, they're clearly ignoring your best intentions - I say let 'em get on with it, but don't provide support for that scenario.
There is nothing you can do to prevent this. Even private members can be accessed via reflection. You should consider the access modifiers in java to be merely suggestive.
First off, this is the “DRM” scenario: ultimately, someone determined enough can defeat any protections you put in place by supplying a funky modified runtime or other such things. The reverse scenario – where the runtime is trusted but some of the packages are not – is tackled properly by Java through the use of suitable ClassLoader restrictions, but that can only work where there's something that can enforce the restrictions in a trusted fashion; that's why your scenario is basically doomed.
However, if we assume that the runtime itself is trustable then you could try, in your super-secret method, getting the stack trace of the currently executing stack (see stackoverflow.com/questions/1069066/… for how) and testing to see whether the caller of the current method is one that you trust to get access. A security manager would be even more suitable, but you can't trust the environment to have one of those installed that you like (it's much more clearly under the control of the attacker). Note that I have not tried the options in this paragraph!
The other alternative is to put your secrets on a service you control and only offer remote access to them. Or stop worrying about using technical mechanisms to deal with a problem that is fundamentally about business and legal issues (e.g., why are you dealing with people you can't trust?)
I'd say simply do not allow them to run code where it can call yours, i.e. in the same JVM. You could instead consider offering only a (web)service they can call externally. I'm not very up to date on the best ways to implement this though.
Why at runtime is anyone interested in knowing that a method is deprecated? Can some provide me with some examples?
There are some frameworks and tools that instantiate objects to work with them.
For example, many JavaBean UI editors create instances of the beans and interact with them as the user manipulates the UI they're designing.
Having the #Deprecated annotation available at runtime allows tools such as this to flag deprecated methods, events, properties for the user.
You're assuming that #deprecated is only of interest in the compile phase (IDE, compiler), but its not a stretch to imaging instrumentation scenarios where you require that information.
For example, an IDE can inform you of the number of call sites for a deprecated method, but how would you go about determining the percentage of time your application spends in deprecated methods?
One's runtime is another one's design time, e.g. when writing code that uses an API.
Good question, and I'm stretching to come up with a convincing scenario. All I've got is that I could imagine a application which used a classloader which didn't allow the use of deprecated code. This would require RetentionPolicy.RUNTIME.
That's all I've got...
Couple practical uses that come to mind:
With Velocity you can have a custom Uberspector which logs the actual calls from Velocity templates to any deprecated method and then just by reading the log you can see where the method is used and you can go and edit it out.
With Wicket you can have a security policy which disallows instantiating any class based on the .class contents so it could be possible to make a system which prevents the instantiation of #Deprecated classes if you're not an admin.
Imagine you compile MyClass.class with deprecated methods. If your #Deprecated annotations got lost, your IDE or compiler couldn't warn you when you call those methods from another class.