I'm a newbie to Android and Java--lots of experience with C/C++/C#.
I have in interface that looks like this:
class WellNamedClass {
void greatMethodToCallWhenever() { /*...*/ }
void debugOnlyMethod() { /*...*/ }
}
In the the languages mentioned above, I would either #ifdef the entire debugOnlyMethod method out or #ifdef the implementation out so it simply does nothing, but Java doesn't have a preprocessor.
I'm totally comfortable with having the code there and checking at run-time whether we are in a debug build, but I can't even find a way of doing that.
I've found suggestions like this one where you create a class with a constant indicating whether debug (or whatever else you want) is enabled. This could work, but then you have to manually change code to get a debug vs. a release build.
Has anyone else solved this problem? Thanks.
I don't know why do you need this, BTW you can put a static global variable, like this:
class WellNamedClass{
public static final boolean DEBUG = true;
...
}
And check your debug method with an if statement, like:
if(WellNamedClass.DEBUG){
debugOnlyMethod();
}
Starting with java you could play with this.
When you get more experience, you could try annotations, aop, or any other advanced programming technique.
This could work, but then you have to manually change code to get a
debug vs. a release build.
One popular approach is to pass system property using -D flag to the VM. You can then either use System.getProperty directly or initialize a static field from that property.
System.getenv will also work.
I think the method we're going to use is have a JNI call into our native component that will tell us whether we are running in debug mode. We have to have the native component anyway, and will make a few JNI calls at startup so it's a relatively simple solution, since C++ has a preprocessor.
Long overdue but it might help anyone else who ends up here in the future.
Simple answer; do not use conditional logic to determine what state the build is in. Configure a build variant and use the appropriate source sets for your configured build. It seems like more work up front but ultimately will save you a ton of time and trouble in the long run.
Related
Whenever I program, I seem to accumulate a lot of "trash" code, code that is not in use anymore. Just to keep my code neat, and to avoid making any expensive and unnecessary computations, Is there an easy way to tell if there is code that is not being used?
One of the basic principles which will help you in this regard is to reduce visibility of everything as much as possible. If a class can be private don't make it default, protected or public. Same applies for methods and variables. It is much easier when you can say for sure if something is not being used outside a class. In cases like this even IDEs like Eclipse and IntelliJ Idea will suggest you about unused code.
Using this practice while developing and refactoring code is the best way to clean unused code confidently without the possibility of breaking the application. This will help in scenarios even when reflection is being used.
It's difficult to do in Java since it's a reflective language. (You can't simply hunt for calls to a certain class or function, for example, since reflection can be used to call a function using strings that can only be resolved at runtime.)
So in full generality, you cannot be certain.
If you have adequate unit tests for your code base then the possibility of redundant code should not be a cause for concern.
I think "unused code" means the code that is always not executed at runtime. I hope I interpreted you correctly.
The way to do a simple check on this is very easy. Just use IntelliJ IDEA to write your code. It will tell you that parts of your code that will never be executed and also the parts where the code can be simplified. For example,
if (x == 5) {
}
And then it will tell you that this if statement is redundant. Or if you have this:
return;
someMethod();
The IDE will tell you that someMethod() can never be reached. And it also provides a lot of other cool features.
But sometimes this isn't enough. What if you have
if (x == 5) {
someMethod();
}
But actually in your code, x can only be in the range of 1 to 4? The IDE won't tell you about this. You can use a tool that shows your code coverage by running lots of tests. Then you can see which part of your code is not executed.
If you don't want to use such a tool, you can put breakpoints in your methods. Then run some tests by hand. When the debugger steps through your code, you can see exactly where the code goes and exactly which piece(s) of code is not executed.
Another method to do this is to use the Find/Replace function of the IDE. Check if some of your public/private methods are not being called anywhere. For example, to check whether someMethod() is called, search for someMethod in the whole project and see if there are occurrences other than the declaration.
But the most effective way would be,
Stop writing this kind of code in the first place!
i think the best way to check that is to install a plugin of coverage like eclemma and create unit and integration tests to get 100% of coverage of the code that accomplish the use code/task you have.
The code that don't need to be tested or don't pass over it after the tests are completed and run, is code that you are not using
Try to avoid accumulating trash in the first place. Remove stuff you don't need anymore. (You could make a backup or better use a source code management system.)
You should also write unit tests for your functions. So you know if it still works after you remove something.
Aside from that, most IDEs will show you unused local variables and private methods.
I do imagine situation when you have app developed by years and some part of your functions doesn't used anymore even they still working. Example: Let's assume you make some changes on internal systems when specific event occured but it is not occurs anymore.
I would say you could use AspectJ to obtain such data / log and then analyze after some time.
Interesting question here. So I have a .jar I received and it is obfuscated, meaning when I decompile the .class files it doesnt show up 100% perfect so I cannot recompile it. However the only method I need to change has been converted perfectly (but the class does not)). Is there a way to somehow change the .java code and inject replace the method within the class file without totally recompiling?
If this fails im going to bytecode.
Thanks!
EDIT: As a follow up question / or a hack around replacing the WHOLE method. I'm really just trying to change a variable that the method generates locally. If there are any better ways to do that.
Depending on what you really want to do, I do not recommand to decompile / modify / recompile the code (be it for legal, maintainance, understandability, testability reasons.)
Bytecode manipulation may not be the best solution either, but if you want to follow this way have a look at the ASM project, it's a widespread bytecode manipulation framework used by many known projects.
If I were you I would first give a try to aspects (AspectJ.) The power of aspects is that you don't touch existing code, but tell the VM what to do when / before / after / in place of calling a specific method. It allows you to point out the exact context and change, enhance the behavior of the code, by writing your own code in a decoupled fashion.
Hope it helps.
Sorry, this is not an answer, but it is too long for a comment...
I am reflecting this code, not using it as a library. So I dont really need to "use" this code (aka I'm just reflecting and calling functions at runtime).
I'd call the "reflecting and calling functions at runtime" as using the code.
There might be the reasons why to do that, but I'd prefer to simply call the function as a library function if possible (which should be possible if you can do the same using reflection).
...and manually overload it.
There is nothing simpler that extending the class and override a "wrong" method. As of my understanding even if you want to "inject" the method, you have to have the code somewhere. How you will test such code? It'd be a lot easier to just extend the class... Can you specify in bigger detail what you want to achieve with a reasoning why you cannot use what I wrote above?
If you want to change just one method you can actually extend the class and then #Override the method!
Don't know if this is the perfect way to do it,but it works!
I am using a Java library, with two classes Foo and FooConfig; I am unable to change the library code, but can read it. Here are the relevant functions of a Foo:
public class Foo
{
/** Install a configuration on this Foo */
void configure(FooConfig config);
/** Uninstall the current configuration */
void unconfigure();
}
The library creates Foos at times I can't control, and installs configurations shortly after creation. A Foo can only have on configuration at a time. I would like to use MyFooConfig, inherited from FooConfig, instead. Is there any way to intercept the configure call, or the FooConfig constructor, or anything like that to use my class instead?
My current solution is to get a reference to the Foo object shortly after its creation and configuration, uninstall the current configuration,and then install a MyFooConfig instead. This could work, but it causes several different problems (both with being a difficult solution to implement and with some inelegancies which can't be hidden from the user). Is there a better way, preferably using features of Java to intercept the constructor call to FooConfig, or the configure method, or something similar? The closest thing to an alternate solution I've found is to try to use a different ClassLoader to replace FooConfig with my own class behind the scenes, but I don't actually have access to the object that creates the FooConfigs so I don't think that's possible. Other things that looked promising but ultimately didn't pan out are proxy objects (I can't make the Foos be proxy objects), seeing if I could somehow get notified when a FooConfig was created without actually intercepting the constructor (so I could find its Foo and reconfigure it in a better way than I`m currently doing), and changing the library code itself (which, for various reasons, turns out to not be possible).
I don't know much about aspect-oriented programming, but it seems like it could help. Unfortunately, all the AOP Java tools seem to require special compilers, and I don't want to change the build process.
I want to hook the method System.out.print in Java and have the ability to read/change the variables used in the method before the part of the method is called that actually adds the string to whatever the output stream is.
In C++ I would just detour the function, or set an int3 instruction so I could access the registers but in java I have no idea how to accomplish something similar.
You can rewrite the byte code of the methods, and in the process capture/change the local variables. It is not trivial. See some notes here.
Maybe what you really want is a java debugger? You can connect a debugger to a remote process, add a breakpoint, and capture/change the local variables pretty easily using eclipse.
What is the real problem you are trying to solve?
Have a look at this link.
He sneakily defines a static anonymous class so that System.out points to something different, and therefore print and println will route through that object.
You can reassign System.out (and System.err) to another object which does what you want to do with it. Said object usually gets the old System.out value so that output can be made in the end.
This is usually done in main() and influences the whole JVM.
We use this to have automatic wrapping at 130 columns in a very peculiar setting where longer lines are truncated.
Since JDK 1.1, the System.setOut and System.setErr methods are added to enable applications to hook the streams.
Link : http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#setOut(java.io.PrintStream)
http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#setErr(java.io.PrintStream)
#Nowayz Some time before i too had the same problem with me.
After some research i came to know About AOP. AOP i.e. AspectJ provides a facility to intercept the java APIs by applying the pointcuts before,after, around. So have a look at it .You can refer my question on stack .it may help you.
Is there something I can call from a POJO to see if the code is currently in an App Server or outside of an App Server?
Something like this (In rough PseudoCode):
System.getRunningEnvironment().equals(Environment.Glassfish)
or
System.getRunningEnvironment().equals(Environment.ApplicationServer)
or
System.getRunningEnvironment().equals(Environment.JavaSE)
If you can change AppServer initialization scripts (take a look at this link):
Add -DRunningInAppServer=true at your AppServer initialization script.
Add -DRunningInAppServer=false at your application initialization script.
Then use this method:
public boolean isRunningInAppServer() {
if ("true".equals(System.getProperty("RunningAppServer"))) {
return true;
}
return false;
}
I don't believe you can do this trivially. And would you want to distinguish between an app server, a web container etc.?
What is the reason for determining this ? To allow your POJOs to behave differently in different environments ? If so then I think this points to an object/component structure that is not quite correct, or at least where the object responsibilities are not clearly defined.
The easiest way is, to check the existence of Java EE/App Server specific classes.
I never used an application server, but maybe you'll be able to achieve this with System.getProperties() / System.getProperty(...)
Consider checking for the current SecurityManager, if your application server uses one.
I don't think there's any way to determine this directly. Yes, as SourceRebel says you could set a system property. Personally I'd avoid doing this, though, as you then have some hidden coupling going on: your function is dependent on a system property that must be set correctly for it to work, but there is nothing clearly defined in the interface to reflect this. I think you'd be far better off to just pass in a parameter that says which it is, and let the caller be responsible to pass in the correct parameter. Then the existence of this parameter can be clearly seen in the function signature, and anyone using it will have a strong clue that they need to set it correctly. Having the caller set it correctly should be trivial, as presumably at some point in the call chain you are either calling from a desktop app or from a web page, and that caller knows which it is.
Some applications server set system properties, JBoss for example:
http://community.jboss.org/wiki/JBossProperties