I'm currently debugging some code that looks like this:
if (!clazz.isAssignableFrom(TypeName.class)){
return
}
Using the standard Eclipse debugging tools, I can inspect both classes and see that their names are both
com.packagename.package1.TypeName
I'd like to step into the isAssignableFrom() method that is being used to fail this evaluation when it seems like it should be passing to narrow down what the issue is. I've followed the answers from this question however, when attempting to "Step Into" isAssignableFrom(), Eclipse skips the line and goes right to the return statement, providing me no information about why two of the exact same type somehow aren't assignable from or to one another.
How can I step into this method to see which comparison is failing in an effort to fix the obvious issue with my TypeName class?
You cannot. It's a native method. There is no Java implementation to step into; it's baked into the JVM.
Likely the classes are loaded from different classloaders.
You could check with cls.getClassLoader().hashCode()
Related
What I'm doing
I'm using reflection in my code to decouple all my classes and To do so I need to be able to dynamically create instances of objects. I've done this by text matching parameter names to input data. To do a text match however, I need access to the formal parameter names rather than the synthetic arg0, arg1 ... that I know gets created if IsNamePresent returns false.
What I've done
I researched how to get the formal names (google searching things like: "when I compile my java classes with the parameter option enabled, does that make reflection work forever? or only one time when the classes are run?" to no useful results). I've also tried searches similar to that here and seen info related to javac with one of the questions being "Drawbacks of javac -parameters flag" as an example. While these addressed parts of my question they really didn't answer the meat of what I need. I've found that in java 8 you can just do "javac -parameters " and you will be fine. Note that I had to use the directory of the jdk as the starting point (my command line input looks exactly like this):
C:\Program Files\Java\jdk-10.0.1\bin>javac -parameters C:\Users\abbotts1\IdeaProjects\project\src\Sales_Rep_Data\*.java
and so far that works without any errors and my project has bytecode compiled files in it now so I know its doing something. Just what exactly (or if its as a result of the above) is a mystery to me because there is no timestamp or anything I can find for these files that points to which command I tried that made it (I've been trying these commands for a while).
Detailed description of question scope
My question is this: is this command line input the only way to get formal parameters. If it is then, am I doing it right (correct input syntax)? If I'm doing it right then how can I make it so that when I debug my code and run param.getName() it actually returns the formal name? So far I've ran the above command on the command line and tried to debug in my java code this line:
Boolean check = param.isNamePresent();
where param is just the parameter coming from a for-each loop that uses the constructor of the class I am getting through reflection. Point is, every-time I run it this Boolean returns false in the debugger and the names are synthetic (arg0, arg1 ect). I want it to return true (and actually use the formal names) so I can debug the rest of my code.
If this isn't the only way to achieve the stated goal of getting formal parameter names then where can I find a better way? I've seen some framework stuff and heard of Eclipse being used to do this, however I don't want to get too deep into new software just to accomplish one thing AND I am working so I don't have administrator privileges (which is why I needed to specify the jdk in cmd directly rather than just set the PATH variables the usual way). This would make it a hassle to have to download something like Eclipse.
Update
I've researched into using annotations to get the parameter names since I have no good idea why the compiled class won't actually store the parameter names. This strategy was suggested in an initial answer (since deleted) and I took it upon myself to go learn some basic annotations. They have worked to a point but right now I'm getting a wrong arguments error where I shouldn't. I've checked the debugger and the number of arguments passed in are the same number needed so it must be a type error with the wrapping/unwrapping according to the javadoc for the newInstance(Object[]) method). I want to be able to initialize null parameters and I think thats the source of my problem (i. e. null type errors or something but not shown as NPE). Other potential sources include the fact that I'm passing in an Object[] and typing it stricter in the class (i.e. newInstance(Object[] array) is creating an instance of a class that has String parameters and other various sub classes of Object including array lists) Since asking about that error here would constitute an XY problem I won't ask but just describe it for clarification on the original question. My original question still stands even as this workaround is being worked on because I'd still love to know why compiling this class with the -parameters flag didn't store the parameter names. I'm 99% sure the class path is correct since I copy pasted it from the directory. This sounds silly but do I have to actually run the class using the below line?
C:\Program Files\Java\jdk-10.0.1\bin>java C:\Users\abbotts1\IdeaProjects\project\src\Sales_Rep_Data\Data_Parser.java
I was under the impression that compiling it with the parameters flag was all you needed and then the formal parameter names would be available.
Is it possible to do method swizzling in android using java? i would like to intercept a system method and log its parameters then process it normally
I think that technique could not be used using Java in any environment.
Maybe you could achieve a similar result using AOP.
But what you can do with that looks limited on Android. See Aspect-oriented programming in android. In fact, since you won't be compiling the target code (system method), compile-time weaving (which appears to be all you could use on Android) will be useless for this case. As is this answer I suppose.
One other thought... I guess you want to do this logging consistently. But if you needed this to debug a problem, you could do it using a conditional breakpoint in Eclipse.
A conditional expression can contain arbitrary Java code and may
contain more than one statement, allowing breakpoint conditions to
implement features like tracing. For example, a condition can execute
a print statement and then return a hard coded value to never suspend
("System.out.println(...); return false;").
I don't know specifically whether this works with methods in the Android SDK. But it does work with methods in the Java SDK. For example, here is simple code:
System.err.println("foo");
I made a conditional breakpoint in PrintStream.print, like this:
System.err.println("hello: " + arg0);
return false;
And the console output when debugging in the program is this:
hello: foo
foo
Note that since the JDK is not compiled with debug symbols, I can't refer to method parameters by name, but using the arg0..argn.
I'm writing a program in Java. I find that reading and debugging code is easiest when the paradigm techniques are consistent, allowing me very quickly assume where and what a problem is.
Doing this has, as you might guess, made my programming much faster, and so I want to find a way to enforce these rules.
For example, lets say I have a method that makes changes to the state of an object, and returns a value. If the method is called outside of the class, I don't ever want to see it resolve inside parameter parentheses, like this:
somefunction(param1, param2, object.change_and_return());
Instead, I want it to be done like this:
int relevant_variable_name = object.change_and_return();
somefunction(param1, param2, relevant_variable_name);
Another example, is I want to create a base class that includes certain print methods, and I want all classes that are user defined to be derived from that base class, much in the way java has done so.
Within my objects, is there a way I can force myself (and anyone else) to adhere to these rules? Ie. if you try to run code that breaks the rules, it will terminate and return the custom error report. Also, if you write code that breaks the rules, the IDE (I use eclipse) will recognize it as an error, underline and call the appropriate javadoc?
For the check and underline violations part:
You can use PMD, it is a static code analyzer.
It has a default ruleset, and you can write custom rules matching what you need.
However your controls seem to be quite complex to express in "PMD language".
PMD is available in Eclipse Marketplace.
For the crash if not conform part
There see no easy way to do it.
Hard/complex ways could be:
Write a rule within PMD, run the analysis at compile time, parse the report (still at compile time) and return an error if your rule is violated.
Write a Java Agent doing the rule check and make it crash the VM if the rule is violated (not sure it is really feasable, agents are meant for instrumentation).
Use reflection anywhere in your code to load classes, and analyze loaded class against your rules and crash the VM if the rule is violated (seriously don't do this: the code would be ugly and the rule easily bypassable).
Is it possible to see the return value of a method after the line has been run and before the instruction pointer returns to the calling function?
I am debugging code I can't modify (read: don't want to re-compile a third party library), and sometimes it jumps to code I don't have source to or the return expression has side effects that stop me being able to just run the expression in the Display tab.
Often the return value is used in a compound statement, and so the Variables view will never show me the value (hence wanting to see the result before control returns to the calling function).
UPDATE: I can't use the expression viewer as there are side-effects in the statement.
This feature was added to Eclipse version 4.7 M2 under Eclipse bug 40912.
To use it:
step over the return statement (using "Step Over" or "Step Return")
now the first line in the variable view will show the result of the return statement, as "[statement xxx] returned: "
See Eclipse Project Oxygen (4.7) M2 - New and Noteworthy for details.
Found a really good shortcut for this.
Select the expression which returns the value and press
Ctrl + Shift + D
This will display the value of the return statement. This is really helpful in cases where you can't or don't want to change just for debugging purpose.
Hope this helps.
Note: Have not tested this with third party libraries, but it is working fine for my code.
Tested this on Eclipse Java EE IDE for Web Developers. Version: Juno Service Release 1
That's why I always stick with the following pattern for methods:
MyReturnedType foo() {
MyReturnedType result = null;
// do your stuff, modify the result or not
return result;
}
My rules:
Only one return statement, only at the end of the method (finally allowed after it)
Always have a local called result which holds the returned value, starting from a default.
Naturally, the most trivial getters are exempt.
This is actually a long standing bug in Eclipse, dating back from the very first days of the IDE: https://bugs.eclipse.org/bugs/show_bug.cgi?id=40912
I am curious about to learn the answer to this question also.
In the past, when dealing with 3rd party library like that, what I did is to create a wrapper class or child class that delegate to the parent class and do my debugging in the wrapper/child class. It takes extra work though.
"Now when you return from a method, in the upper method, in the variable view it shows the return value of the previously finished call" [1]
[1] https://coffeeorientedprogramming.wordpress.com/2016/09/23/eclipse-see-return-value-during-debugging/
Tough one. My experience, outside of Eclipse, is that if you might need to see the return value, it is best to assign it to a local variable in the function so that the return statement is a simple return varname; and not return(some * expression || other);. However, that's not dreadfully helpful to you since you say you can't (or don't want to) modify or even recompile the code. So, I don't have a good answer for you - perhaps you need to reconsider your requirement.
Depending on the return statement, you can highlight the expression that is being returned and from the right-click menu, there should be something like "evaluate expression" (I don't have eclipse in front of me now, but it's something like that). It will show you what is going to be returned.
This is a bit far-fetched, but as there doesn't seem to be a simple way:
You could use AspectJ to instrument the JAR with aspects that get hold of the return value of the methods you're interested in. According to Eclipse's documentation, AspectJ programs can be debugged like other programs.
There are two options to weave your classes without recompiling the library :
Post-compile weaving if processing the binary JAR is acceptable;
Load-time weaving, which requires activating a weaving agent in the VM.
See the eclipse documentation (link above) and also the AspectJ Development Environment Guide.
For #Daniel Meyer answer's to work, ensure that 'Show method result after a step operation (if supported by the VM; may be slow)' is checked. The option is accessible via;
Windows> Preferences> Java> Debug> Show method result......
I have a class A<X, Y> and I want to refactor it to A<Y, X> in a way that all the references to it would be modified as well.
I don't think that has been implemented in Eclipse yet. It's a rather rare refactoring, though...
But if your type hierarchy below A is not too complex yet, try using this regex-search-replace (where A|B|C means A and all subtypes of A, e.g. B and C):
\b(A|B|C)<\s*(\w+)\s*,\s*(\w+)\s*>
update: since you want to match more sophisticated stuff, try this (without the artifical line-breaks):
\b(A|B|C)<
\s*((?:\w+|\?)(?:\s+(?:extends|super)\s+(?:\w+|\?))?)\s*,
\s*((?:\w+|\?)(?:\s+(?:extends|super)\s+(?:\w+|\?))?)\s*>
replace by
$1<$3, $2>
Since you're using Eclipse, you can manually check every replacement for correctness
In Eclipse right-click on the method, then Refactor->Change method signature, you can change the order of the parameters there
If you aren't using Eclipse (or another tool that has good refactoring - highly recommended if you're aren't), then I can think of two ways to do this:
First:
If you're using TDD, then write a test that will only succeed when the variables are properly swapped. Then make the change to the method signature, and make sure your test passes.
Second:
1. Remove the 2nd parameter from the method signature, which will throw compilation errors on all calls to that method
2. Go to each of the lines that are failing compilation, and carefully swap the variables
3. Put the 2nd variable back into the method signature, in the new, reversed order
4. Run some tests to make sure it still works the way you expect it to
The second method is obviously ugly. But if you're aren't using an IDE with good refactoring support, compilation errors are a good way to capture 100% of the calls to that method (at least within your project). If you're writing a code library that is used by other people, or by other programs, then it becomes much more complicated to communicate that change to all affected parties.