I was wondering what are the main reasons why eclipse warns developers about the following things:
The value of the local variable xxx is not used
The import XXX is never used
I'm thinking that one reason is to make code cleaner. Anyone knows a list of reasons behind those warnings (like memory concerns, and things like that)?
Thanks!
It's mostly to make the code readable and avoid clutter - it's easy to loose track when a file starts getting large, and having non-functional lines of code are therefor best to avoid. It's mostly for readability... Well, and by removing unused imports, you ease the compilers job ever so slightly (read: very slightly).
If Eclipse notice an unused import or variable, you can be damn sure that the compiler does so as well (since eclipse is actually compiling the code while you code to generate those warnings). The compiler will try to optimize it as much as possible, so if it sees an unused variable (or import), it doesn't bother to include them in the compiled byte code.
But it's generally good coding style not to have unused code;
In Java and (most) other high-level languages, you generally don't have to worry about those things, since you don't have to manage memory-allocation. But supposing the compiler didn't catch it for whatever reason when compiling (perhaps if you were writing in another programming language), the object or data referenced by a variable would then be taking up memory space, and if you a lot of those unused variables that all took up memory space... that could potentially be a lot of memory used for nothing.
Yes why should you include code, that is never used?
I guess the compiler will remove this unused code anyway, but you should keep the code as clean as possible by yourself.
The value of the local variable xxx is not used
It is declared when you only declare or assign a value to a variable, but you never used it for anything. It is warning you because it does nothing in your code, so it would be better to remove it.
The import XXX is never used
The same thing as the other one. There is no need to import a classe you won't use, so Eclipse recommends you to remove the import, since it does nothing but pollute the code.
This prevents you that you writed Unnecessary code. According to the help of Eclipse (Java Compiler Errors/Warnings Preferences) this says :
"When enabled, the compiler will issue an error or a warning whenever
a local variable is declared but its value never used within its
scope."
you are unnecessarily declared/imported the variable/import.
Removing them keeps the code cleaner and easier to read.By default Eclipse warns you about unused private variables and methods.
But do not change these warning preferences,It's helpful to identify your unused code.
Related
I have a problem with an old application which runs on a Java Tomcat server and the source code for the application is not fully available, but the .class files are obviously all running on the tomcat server.
Can I somehow manipulate the bytecode of a .class file (used by JVM) so that I can change a variables datatype (because this is what has to be done)? Or even reverse engineer it to its old .java source code?
I have used decompilers and javap command up to now. Can I somehow copy the whole Tomcat application and:
decompile it
do my changes
recompile it?
Well, if you decompile it to make changes and recompile, then you're not going to need to change the byte code directly.
If you change the type, you'll have to change the type of any methods (like getters and setters) that use the variable. Then you'll need to change the calls of any methods in all classes that CALL those methods, and the types of their variables that hold these values, etc. The good news is that, if you manage to decompile it successfully, your IDE will tell you where all those places are, assuming the new type is incompatible with the old type.
I would evaluate this as "theoretically possible", but problematic. With the little information you've given us, there's no way to know the size of the job AFTER you successfully decompile the entire application.
I have a wild and crazy idea; I haven't done this, but as long as we're talking about things that are theoretically possible...
IF you manage to decompile all the code and get a system that you can recompile and run (and I strongly recommend you do that before you make any changes), if you are able to identify where the int is that you want to replace with a long, and then all the direct and indirect references to it, hopefully (because it's just this file size limit that you mention elsewhere) you end up with only a handful of classes.
The decompile should tell you their names. Create new classes with the exact same names, containing (of course) all their decompiled code. Change the methods that you need to change.
Now put those classes in a jar that is searched before the jar containing the application. You're limiting the number of classes for which you're providing new .class files to just those. This makes it easier to see exactly what has been changed, for future programmers, if it doesn't do anything else. It's possible because of the way Java handles its runtime; the step that's equivalent to 'linking' in a traditional compiled non-virtual-machine language happens when the class is loaded, instead of at compile time.
I did that. Not exactly that, but something very similar. Instead of decompiling and recompiling, which is very long, and tedious, I directly edited the byte-code of the class file.
pros
You do not need to compile anything at all, you just edit a file
no SDK, no IDE, etc is necessary, just a java-byte code editor
for small changes you can get away with single method modification
cons
very-very error-prone even if you know what you are doing
no way to track changes as you do with git
will probably require modifying all dependent classes
you should have some knowledge about how compiled code looks like, and behaves before even attempting such a thing.
you will most likely break a law or two since this will not be for "educational" purposes
you will be marked as "the hacker" and every odd job will be forwarded to you
PS: I had to edit licensing class of a product to allow more users. The company writing it ceased to exist, so buying was not an option. We switched to a new product anyway, it was just temporarily.
I use Eclipse and have some project compiled and running. Then I decide to modify some class.
It seems that running project doesn't catch up changes, but if I run another instance of project then it does see changes.
The question, how does Eclipse rule this out?
Because I see that .class files are stored as single instance and later changes just overwrite previous. It maybe JVM who load classes in memory and don't touch them even if they changed. But I would like to hear complete story.
When a program runs, it reads the .class file into memory and uses that copy from then on.
If you change, it doesn't re-read the file and load/link it again, that would be more complicated. There are class loaders which do this automagically, but this is not default behaviour. (It is also very unreliable as you might change the class in an incompatible way e.g. modify a field, or method signature)
Generally speaking, software is implemented in the simplest way imaginable. It is more likely to work and be understood if it is simple. This should be your guiding principle when trying to understand how computers work.
I need to manually add a method call to a class file without decompiling and recompiling the code because It depends on thousands of other classes and I don't wan't have to do more than is nessescary. I know java but not how class files are made.
Any help is appreciated.
EDIT:
I am not the owner of the source and I need this to work on any computer, which means I cannot redistribute the sources and have them compiled realtime while my patcher is working.
You have the source code, and you have all other classes compiled. So you can recompile just that source file, passing compiled classes as parameters to java compiler with -classpath option.
You should use ASM or Javaassist to manipulate the bytecode. ASM is a little bit more complex and requires you to understand more about the JVM, but it's faster. Javaassist doesn't require you to know much about the JVM's internals.
However, I don't see why you can't just recompile that single sourcefile? If you only need to add this method once, it's very inefficient to learn ASM or Javaassist.
How about subclassing? Then you don't need to touch the sources.
So if you have the source code and want to add some methods into only one class. Then you don't have to worry about other classes even they are dependent on your current modified class. Re-compiling a file doesn't affect other classes. Since the output will be produced at run-time.
If your class is not declared final and the method you are interested is not final, you can extend the class and override just that method.
Just change the source code, recompile ! Everything will work fine. Subclassing won't work .Because Already existing classes won't know about the new subclass until you change their code to use the new subclass instead of old superclass.
For manual editing of classfiles, I'd recommend Krakatau. (Disclosure, I wrote it). It lets you disassemble a classfile, edit it, and reassemble. There are other assemblers out there, but AFAIK, Krakatau is the only one that supports all the weird edge cases in the classfile format.
The main caveat is that Krakatau by default does not preserve certain optional debugging attributes (specifically LineNumberTable, LocalVariableTable, and LocalVariableTypeTable), since there is no simple way to represent them in a human editable format, and failing to edit them when the bytecode changes will result in a verification error. Most likely you don't actually need this though so it shouldn't matter.
The other caveat of course is that you have to understand bytecode. But if you don't, you won't be able to manually edit classfiles anyway.
I got it now! I Created fake source files with the same names/methods but didn't add anything else except for class and method names. That way I only needed to pack the ones that are directly linked to my Class file. But now compiling takes a few milliseconds whereas it used to take around 124s, Lol. Works great!
Can I remove any implicitly imported Java library?
It may not seem useful.
But I think it may reduce some execution time!
Imports are just syntactic sugar. All they do is let you access things in other packages without having to state their fully qualified name. The code that is produced is exactly the same as if you fully-qualified everything. So there is no runtime performance penalty to having imports.
This also goes for the "implicit imports" (ie: java.lang): you don't pay any price for the classes you don't actually use.
This will have no effect on execution type - I think I'm correct in saying that, by default, classes are only loaded as and when they are needed, not on mass at start-up.
To improve performance you need to profile your application with a tool like Visual VM and address the bottlenecks it identifies (which will never be where you'd expect).
Java doesn't include all of the classes in java.lang.* in your program. The compiler only includes the ones you explicitly use (or are used by classes you use, etc.).
Normally it's easy to see unused variables in Netbeans, just a grey squiggly line.
But how would I find all of these unused variables in my project or of a single class?
Reason: I'm debugging a code base which had lots of copy and paste, but it wasn't done carefully. There's many bug of not replacing with the right variable after copy and paste.
You could run something like FindBugs on it.
FindBugs
Looking at the bug list it has
UuF: Unused field (UUF_UNUSED_FIELD)
This field is never used. Consider removing it from the class.
You could filter on just this, but it is a good idea to run this on all code all the time, it is amazing what it finds.
PMD will find unused local variables for you (among many other things). There's a NetBeans plugin that I give installation instructions for here (Warning: Shameless Plug, that links to my blog).
In Eclipse, that gray squiggly line is a yellow squiggly line called a Warning. Then the warning is propagated up to the package level, and up to the project level (such that your project is almost always underlined in yellow with a warning icon). Anyway it really helps you see which source files have warnings in them.
Then your task is to solve every warning in the entire project, and you will have caught the unhandled variables.
I assume netbeans has the same feature somewhere.
The compiler will warn about unused variables giving you your list.
Unused method variables will be removed by the compiler but unused member variables remain, which depending on the state of your codebase may make this a cosmetic problem that can be handled as and when each file is modified rather than a conserted effort to remove all unused variables in one go.
Saying that, I generally like my builds to run with no warnings, so that when I genuinely break something I notice the warning. Maybe this is the clean-up you are looking for ;-)