why is there an issue with scope of the variable? - java

Can someone please help identify what is the issue with the below code... and why is there a problem in compiling for the variable "i$"
Below is the code....
private void handlePendingFilesForPreviousCheckpoints(Map<Long, List<String>> pendingFilesPerCheckpoint) {
LOG.debug("Moving pending files to final location on restore.");
Set<Long> pastCheckpointIds = pendingFilesPerCheckpoint.keySet();
Iterator i$ = pastCheckpointIds.iterator();
while(i$.hasNext()) {
Long pastCheckpointId = (Long)i$.next();
Iterator i$ = ((List)pendingFilesPerCheckpoint.get(pastCheckpointId)).iterator();
while(i$.hasNext()) {
String filename = (String)i$.next();
Path finalPath = new Path(filename);
Path pendingPath = this.getPendingPathFor(finalPath);
try {
if(this.fs.exists(pendingPath)) {
LOG.debug("Restoring BucketingSink State: Moving pending file {} to final location after complete checkpoint {}.", pendingPath, pastCheckpointId);
this.fs.rename(pendingPath, finalPath);
}
} catch (IOException var10) {
LOG.error("Restoring BucketingSink State: Error while renaming pending file {} to final path {}: {}", new Object[]{pendingPath, finalPath, var10});
throw new RuntimeException("Error while renaming pending file " + pendingPath + " to final path " + finalPath, var10);
}
}
}
}
Even though the i$ is defined inside curly braces second time... it says, the variable i$ is already defined in the scope....
Can someone please help me fix this... and understand what is wrong with the variable i$ in the above code.
Thanks a lot.

The scope of a variable is the (entire) block in which it's defined, which of course includes all sub-blocks within the declaring block.
To fix the problem, use different variable names.

You commented this:
but wondering, why this is creating problem... as i copied this method from other class and that is working fine... but mine is creating problem.... can you please explain
OK what you actually did is that you decompiled a class and copied the decompiled code into your source code.
That approach often doesn't work. And yours is an example where it hasn't worked.
The design goals for a typical Java decompiler is to translate compiled code into something that a programmer can read. The decompiled code above satisfies this. A typical Java programmer reading the above will understand what the original code was trying to do.
However there are a couple of non-goals for a decompiler:
It is NOT a goal to reproduce the original source code. (It is mathematically impossible to do that!)
It is NOT a goal to produce code that is "best practice" in style. That is impractical for a number of reasons. (For a start, people can't agree on what best practice is!)
In is NOT a goal to produce code that is always compilable. It might be possible for bytecodes that haven't been obfuscated, but:
it is really hard to cover the edge cases,
it is impossible to prove that you have covered all of the edge cases
and the set of compilers whose code you need to support is growing all of the time.
What does this mean in practice?
In practice code that is generated by a decompiler is generally1 readable, and may be compilable, but:
you may need to correct compilation errors
the code is not as maintainable as the original source code2
the code is not suitable for use as an example of how to program.
1 - However, if the bytecodes have been obfuscated, all bets are off. The purpose of obfuscation is to make it difficult to decompile code and / or understand the decompiled code.
2 - For a start, when you compile code, the compiler discards all source code comments and (typically) the names of local variables. Then it transforms various constructs such as enhanced loops, inner classes and lambdas into simpler forms that the JVM supports. These transformations are not reversible.

A simple (but possibly not the best) solution is to just call the inner iterator something else like ir or something.
Ex. Change this line:
Iterator i$ =
((List)pendingFilesPerCheckpoint.get(pastCheckpointId)).iterator();
to something like this:
Iterator ir =
((List)pendingFilesPerCheckpoint.get(pastCheckpointId)).iterator();

Related

Does a Java compiler optimize ad hoc instances of `Set.of`, `List.of`, and `Map.of` in loops as constants

Given the following code snippet in which an ad hoc instance of a Set is created, will todays Java compiler see that they do not need to create the instance for each loop pass and optimize set as a kind of final constant such that the instance is the same for the entire loop? The question applies similarly to while and do while loops.
for (/* a loop that iterates quite often */)
{
var set = Set.of("foo", "blah", "baz");
// Do something with the set.
}
I would also be interested whether such an optimization is done already at compile-time (meaning that the byte code is already optimized) or whether there exist runtime optimizations (made by the just-in-time compiler) that essentially achieve the same.
If a compiler does not see this, the only option seems to instantiate the set outside the loop in order to be optimal:
var set = Set.of("foo", "blah", "baz");
for (/* a loop that iterates quite often */)
{
// Do something with the set.
}
Side note, for those finding the first snippet rather bad practice and that would write it like the second snippet anyway: This snippet is actually a simplified variant of my real use case, made for simplicity reasons of the question. The real, slightly more complex use case that brought me to this question is the following, where a string needs to be checked whether it is one of a very few strings:
for (/* a loop that iterates quite often */)
{
// ...
var testString = // some String to check ...
if (Set.of("foo", "blah", "baz").contains(testString))
{
// Do something.
}
// ...
}
Assuming that the if condition is surrounded by additional code (i.e., the loop body is rather large), I think one wants to declare the set inline rather than further away outside the loop.
The answer will inevitably depend on the Java tools that you use.
The javac bytecode compiler is (deliberately) naive, and I would not expect it to do any optimization of this. The JVM's JIT compiler may optimize this, but that will depend on:
your Java version,
the JIT compiler tier used
what /* do something with the set */ actually entails.
If this really matters to you, I would advise a couple of approaches.
Rewrite the code yourself to hoist the Set declaration out of the loop. IMO, there is nothing fundamentally wrong with this approach, though it is potentially a premature optimization. (I'd probably do this myself in the examples you gave. It just "feels right" to me.)
Use the JVM options for dumping out the native code produced by the JIT compiler and see what it actually does. But beware that the results are liable to vary: see above.
But even if you know with a good degree of certainty how the compilers will do, it is not clear that you should be worrying about this in general.
Note looking at the bytecodes with javap -c will tell you if the java compiler is doing any optimization. (Or more likely, confirm that it isn't.)

Memory/Performance differences of declaring variable for return result of method call versus inline method call

Are there any performance or memory differences between the two snippets below? I tried to profile them using visualvm (is that even the right tool for the job?) but didn't notice a difference, probably due to the code not really doing anything.
Does the compiler optimize both snippets down to the same bytecode? Is one preferable over the other for style reasons?
boolean valid = loadConfig();
if (valid) {
// OK
} else {
// Problem
}
versus
if (loadConfig()) {
// OK
} else {
// Problem
}
The real answer here: it doesn't even matter so much what javap will tell you how the corresponding bytecode looks like!
If that piece of code is executed like "once"; then the difference between those two options would be in the range of nanoseconds (if at all).
If that piece of code is executed like "zillions of times" (often enough to "matter"); then the JIT will kick in. And the JIT will optimize that bytecode into machine code; very much dependent on a lot of information gathered by the JIT at runtime.
Long story short: you are spending time on a detail so subtle that it doesn't matter in practical reality.
What matters in practical reality: the quality of your source code. In that sense: pick that option that "reads" the best; given your context.
Given the comment: I think in the end, this is (almost) a pure style question. Using the first way it might be easier to trace information (assuming the variable isn't boolean, but more complex). In that sense: there is no "inherently" better version. Of course: option 2 comes with one line less; uses one variable less; and typically: when one option is as readable as another; and one of the two is shorter ... then I would prefer the shorter version.
If you are going to use the variable only once then the compiler/optimizer will resolve the explicit declaration.
Another thing is the code quality. There is a very similar rule in sonarqube that describes this case too:
Local Variables should not be declared and then immediately returned or thrown
Declaring a variable only to immediately return or throw it is a bad practice.
Some developers argue that the practice improves code readability, because it enables them to explicitly name what is being returned. However, this variable is an internal implementation detail that is not exposed to the callers of the method. The method name should be sufficient for callers to know exactly what will be returned.
https://jira.sonarsource.com/browse/RSPEC-1488

Analyzing a variable inside a method. JavaParser/ANTLR or something else?

I am writing a java code analyzing snippet which will find out the use of variables in a method. (to be specific how many times a global class variable is read and written in a method). Can this be done using JavaParser? Would anyone have any other recommendations? Does any one know how class metrics are calculated? They probably deal with similar things.
Thanks guys. Both your answers lead me in a direction to solution to this problem using the AST implementation in JAVAPARSER. Here's a code snippet to help others
class CatchNameExpr extends VoidVisitorAdapter {
HashMap<String, ArrayList<Integer>> variableLineNumMap;``
ArrayList<String> variableList;
boolean functionParsing = false;
public CatchNameExpr(ArrayList<String> classVariables) {
variableList=classVariables;
}
public void visit(MethodDeclaration method, Object arg) {
System.out.println("---------------");
System.out.println(method.getName());
System.out.println("---------------");
variableLineNumMap = new HashMap<String, ArrayList<Integer>>();
System.out.println();
functionParsing = true;
visit(method.getBody(),arg);
// Analyze lines for variable usage. Add to list of vars after checking if its read or written or unknown.
functionParsing = false;
}
public void visit(NameExpr n, Object arg) {
if(!functionParsing)
return;
//TODO: check if this var was declared above it, as a local var to the func. if yes, return
ArrayList<Integer> setOfLineNum;
System.out.println(n.getBeginLine()+" NameExpr " + n.getName());
if(!variableList.contains(n.getName()) || n.getName().length()==0)
return;
if (!variableLineNumMap.containsKey(n.getName()))
{
setOfLineNum = new ArrayList<Integer>();
setOfLineNum.add(n.getBeginLine());
variableLineNumMap.put(n.getName(), setOfLineNum);
}
else
{
setOfLineNum = variableLineNumMap.get(n.getName());
setOfLineNum.add(n.getBeginLine());
variableLineNumMap.put(n.getName(), setOfLineNum);
}
}
}
Instantiate the class --->
CatchNameExpr nameExp = new CatchNameExpr(classVariables);
nameExp.visit(classCompilationUnit, null);
In a similar manner you can visit the AST for the following expressions, statements, condition etc
http://www.jarvana.com/jarvana/view/com/google/code/javaparser/javaparser/1.0.8/javaparser-1.0.8-javadoc.jar!/japa/parser/ast/visitor/VoidVisitorAdapter.html
I am well aware that byte-code processor will be more efficient, and will do the job better than i can hope for. But given the time limit, this option fitted me the best.
Thanks guys,
Jasmeet
To do the task of finding usages of variables, a parser buld with ANTLR should also produce AST. I am almost sure you can find ready AST builder, but don't know where.
Another approach is to analyze class files with ASM, BCEL or other class file analyzer. I think it is easier, and would work faster. Besides, it would work for other jvm languages (e.g. Scala).
To ask questions as to whether a variable read is "global" or not, you need what amounts to a full Java compiler front end, that parses code, build symbol tables and related type information.
To the extent the compiler has actually recorded this information in your class files, you may be able to execute "reflection" operations to get your hands it. To the extent that such information is present in .class files, you can access it with class-file byte-code processor such as those mentioned in Kaigorodov's answer.
ANTLR has a grammar for Java, but I don't believe any support for symbol table construction.
You can't fake this yourself; Java's rules are too complex. You might be able to extend the ANTLR parser to do this, but it would be a LOT of work; "Java's rules are too complex".
I understand the Java compiler offers some kind of name/type accurate access to its internal structures; you might be able to use that.
Our DMS Software Reengineering Toolkit has full Java parsers, with name and type resolution, and could be used for this purpose.

Why does Java have an "unreachable statement" compiler error?

I often find when debugging a program it is convenient, (although arguably bad practice) to insert a return statement inside a block of code. I might try something like this in Java ....
class Test {
public static void main(String args[]) {
System.out.println("hello world");
return;
System.out.println("i think this line might cause a problem");
}
}
of course, this would yield the compiler error.
Test.java:7: unreachable statement
I could understand why a warning might be justified as having unused code is bad practice. But I don't understand why this needs to generate an error.
Is this just Java trying to be a Nanny, or is there a good reason to make this a compiler error?
Because unreachable code is meaningless to the compiler. Whilst making code meaningful to people is both paramount and harder than making it meaningful to a compiler, the compiler is the essential consumer of code. The designers of Java take the viewpoint that code that is not meaningful to the compiler is an error. Their stance is that if you have some unreachable code, you have made a mistake that needs to be fixed.
There is a similar question here: Unreachable code: error or warning?, in which the author says "Personally I strongly feel it should be an error: if the programmer writes a piece of code, it should always be with the intention of actually running it in some scenario." Obviously the language designers of Java agree.
Whether unreachable code should prevent compilation is a question on which there will never be consensus. But this is why the Java designers did it.
A number of people in comments point out that there are many classes of unreachable code Java doesn't prevent compiling. If I understand the consequences of Gödel correctly, no compiler can possibly catch all classes of unreachable code.
Unit tests cannot catch every single bug. We don't use this as an argument against their value. Likewise a compiler can't catch all problematic code, but it is still valuable for it to prevent compilation of bad code when it can.
The Java language designers consider unreachable code an error. So preventing it compiling when possible is reasonable.
(Before you downvote: the question is not whether or not Java should have an unreachable statement compiler error. The question is why Java has an unreachable statement compiler error. Don't downvote me just because you think Java made the wrong design decision.)
There is no definitive reason why unreachable statements must be not be allowed; other languages allow them without problems. For your specific need, this is the usual trick:
if (true) return;
It looks nonsensical, anyone who reads the code will guess that it must have been done deliberately, not a careless mistake of leaving the rest of statements unreachable.
Java has a little bit support for "conditional compilation"
http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.21
if (false) { x=3; }
does not result in a compile-time
error. An optimizing compiler may
realize that the statement x=3; will
never be executed and may choose to
omit the code for that statement from
the generated class file, but the
statement x=3; is not regarded as
"unreachable" in the technical sense
specified here.
The rationale for this differing
treatment is to allow programmers to
define "flag variables" such as:
static final boolean DEBUG = false;
and then write code such as:
if (DEBUG) { x=3; }
The idea is that it should be possible
to change the value of DEBUG from
false to true or from true to false
and then compile the code correctly
with no other changes to the program
text.
It is Nanny.
I feel .Net got this one right - it raises a warning for unreachable code, but not an error. It is good to be warned about it, but I see no reason to prevent compilation (especially during debugging sessions where it is nice to throw a return in to bypass some code).
I only just noticed this question, and wanted to add my $.02 to this.
In case of Java, this is not actually an option. The "unreachable code" error doesn't come from the fact that JVM developers thought to protect developers from anything, or be extra vigilant, but from the requirements of the JVM specification.
Both Java compiler, and JVM, use what is called "stack maps" - a definite information about all of the items on the stack, as allocated for the current method. The type of each and every slot of the stack must be known, so that a JVM instruction doesn't mistreat item of one type for another type. This is mostly important for preventing having a numeric value ever being used as a pointer. It's possible, using Java assembly, to try to push/store a number, but then pop/load an object reference. However, JVM will reject this code during class validation,- that is when stack maps are being created and tested for consistency.
To verify the stack maps, the VM has to walk through all the code paths that exist in a method, and make sure that no matter which code path will ever be executed, the stack data for every instruction agrees with what any previous code has pushed/stored in the stack. So, in simple case of:
Object a;
if (something) { a = new Object(); } else { a = new String(); }
System.out.println(a);
at line 3, JVM will check that both branches of 'if' have only stored into a (which is just local var#0) something that is compatible with Object (since that's how code from line 3 and on will treat local var#0).
When compiler gets to an unreachable code, it doesn't quite know what state the stack might be at that point, so it can't verify its state. It can't quite compile the code anymore at that point, as it can't keep track of local variables either, so instead of leaving this ambiguity in the class file, it produces a fatal error.
Of course a simple condition like if (1<2) will fool it, but it's not really fooling - it's giving it a potential branch that can lead to the code, and at least both the compiler and the VM can determine, how the stack items can be used from there on.
P.S. I don't know what .NET does in this case, but I believe it will fail compilation as well. This normally will not be a problem for any machine code compilers (C, C++, Obj-C, etc.)
One of the goals of compilers is to rule out classes of errors. Some unreachable code is there by accident, it's nice that javac rules out that class of error at compile time.
For every rule that catches erroneous code, someone will want the compiler to accept it because they know what they're doing. That's the penalty of compiler checking, and getting the balance right is one of the tricker points of language design. Even with the strictest checking there's still an infinite number of programs that can be written, so things can't be that bad.
While I think this compiler error is a good thing, there is a way you can work around it.
Use a condition you know will be true:
public void myMethod(){
someCodeHere();
if(1 < 2) return; // compiler isn't smart enough to complain about this
moreCodeHere();
}
The compiler is not smart enough to complain about that.
It is certainly a good thing to complain the more stringent the compiler is the better, as far as it allows you to do what you need.
Usually the small price to pay is to comment the code out, the gain is that when you compile your code works. A general example is Haskell about which people screams until they realize that their test/debugging is main test only and short one. I personally in Java do almost no debugging while being ( in fact on purpose) not attentive.
If the reason for allowing if (aBooleanVariable) return; someMoreCode; is to allow flags, then the fact that if (true) return; someMoreCode; does not generate a compile time error seems like inconsistency in the policy of generating CodeNotReachable exception, since the compiler 'knows' that true is not a flag (not a variable).
Two other ways which might be interesting, but don't apply to switching off part of a method's code as well as if (true) return:
Now, instead of saying if (true) return; you might want to say assert false and add -ea OR -ea package OR -ea className to the jvm arguments. The good point is that this allows for some granularity and requires adding an extra parameter to the jvm invocation so there is no need of setting a DEBUG flag in the code, but by added argument at runtime, which is useful when the target is not the developer machine and recompiling & transferring bytecode takes time.
There is also the System.exit(0) way, but this might be an overkill, if you put it in Java in a JSP then it will terminate the server.
Apart from that Java is by-design a 'nanny' language, I would rather use something native like C/C++ for more control.

Java Code Use Checker

I am working on a library where we want to determine how much of our library is being used. I.E. we want to know how many methods in our library are public, but never being called.
Goal:
Static Analysis
Determine how many lines of code call each public method in package A in the current project. If the number of calls is zero, the method should be reported as such.
I belive you are looking for this eclipse plugin --> UCDetector
From the documentation (pay notice to second bullet point)
Unnecessary (dead) code
Code where the visibility could be changed to protected, default or
private
Methods of fields, which can be final
On Larger scale, if you want to do Object Level Static Analysis, look at this tool from IBM -->Structural Analysis for Java. It is really helpful for object analysis of libraries, APIs, etc.
Not exactly what you are looking for, but:
Something similar be done with code coverage tools (like Cobertura). They do not do static inspection of the source code, but instrument the bytecode to gather metrics at runtime. Of course, you need to drive the application in a way that exercises all usage pattern, and might miss the rarer code paths.
On the static analysis front, maybe these tools can help you (the Apache project uses them to check for API compatibility for new releases, seems like that task is somewhat related to what you are trying to do):
Clirr is a tool that checks Java libraries for binary and source compatibility with older releases. Basically you give it two sets of jar files and Clirr dumps out a list of changes in the public api.
JDiff is a Javadoc doclet which generates an HTML report of all the packages, classes, constructors, methods, and fields which have been removed, added or changed in any way, including their documentation, when two APIs are compared.
Client use of reflective calls is one hole in static analysis to consider. As there's no way to know for sure that a particular method isn't being called via some bizarre reflection scheme. So, maybe a combination of runtime and static analysis might be best.
I don't think you are able to measure how "often" a class or a function is needed.
There are some simple questions:
What defines, if a usage statistic of your game library is "normal" or an "outlier"? Is it wrong to kill yourself in the game too often? You would use the "killScreen" class more frequently like a good gamer.
What defines "much"? Time or usage count? POJOs will consume rare time, but are used pretty frequently.
Conclusion:
I don't know what you are trying to accomplish.
If you want to display your code dependencies, there are other tools for doing this. If you're trying to measure your code execution, there are profiler or benchmarks for Java. If you are a statistic geek, you'll be happy with RapidMiner ;)
Good luck with that!
I would suggest JDepend shows you the dependencies between packages and classes, excellent to find cyclic dependencies!
http://clarkware.com/software/JDepend.html
(it has an eclipse plugin: http://andrei.gmxhome.de/jdepend4eclipse/
and also PMD for other metrics
http://pmd.sourceforge.net/
IntelliJ has a tool to detect methods, fields, class which can have more restricted modifiers. It also a has a quick fix to apply these changes which can save you a lot of work as well. If you don't want to pay for it, you can get the 30-day eval license which is more than enough time to change your code, its not something your should need to do very often.
BTW: IntelliJ has about 650 code inspections to improve code quality, about half has automatic fixes so I suggest spend a couple of day using it to refactor/tidy up your code.
Please take a look at Dead Code Detector. It claims to do just what you are looking for: finding unused code using static analysis.
Here's are a few lists of Java code coverage tools. I haven't used any of these personally, but it might get you started:
http://java-source.net/open-source/code-coverage
http://www.codecoveragetools.com/index.php/coverage-process/code-coverage-tools-java.html
Proguard may be an option too (http://proguard.sourceforge.net/):
"Some uses of ProGuard are:
...
Listing dead code, so it can be removed from the source code.
... "
See also http://proguard.sourceforge.net/manual/examples.html#deadcode
You could write your own utility for that (within an hours after reading this) using the ASM bytecode analysis library (http://asm.ow2.org). You'll need to implement a ClassVisitor and a MethodVisitor. You'll use a ClassReader to parse the class files in your library.
Your ClassVisitor's visitMethod(..) will be called for each declared method.
Your MethodVisitor's visitMethodInsn(..) will be called for each called method.
Maintain a Map to do the counting. The keys represent the methods (see below). Here's some code:
class MyClassVisitor {
// ...
public void visit(int version, int access, String name, ...) {
this.className = name;
}
public MethodVisitor visitMethod(int access, String name, String desc, ...):
String key = className + "." + name + "#" + desc;
if (!map.containsKey() {
map.put(key, 0);
}
return new MyMethodVisitor(map);
}
// ...
}
void class MyMethodVisitor {
// ...
public visitMethodInsn(int opcode, String name, String owner, String desc, ...) {
String key = owner + "." + name + "#" + desc;
if (!map.containsKey() {
map.put(key, 0);
}
map.put(key, map.get(key) + 1);
}
// ...
}
Basically that's it. Your're starting the show with something like this:
Map<String,Integer> map = new HashMap<String,Integer>();
for (File classFile : my library) {
InputStream input = new FileInputStream(classFile);
new ClassReader(input).accept(new MyClassVisitor(map), 0);
input.close();
}
for (Map.Entry<String,Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
System.out.println("Unused method: " + entry.getKey());
}
}
Enjoy!

Categories

Resources