Eclipse JDT - How to watch non-public variables? - java

I am not new to programming but I am just learning the Java language and Eclipse. I want to see how Java works internally for some of the various "standard" imported classes using Eclipse's debug facilities (JDT Debug). My setup (Oxygen w/ JDK SE8 on Windows 8.1) works fine as far as single stepping through the code but many of the imported Class variables are unable to be placed into a watchlist or expression monitor, which I think is because they are not defined as "public".
As an example: I want to learn how java.math.BigInteger works so I wrote a quick program which uses the pow() method. The program runs successfully, and when using debug mode I am able to track the flow fine as well. What I cannot seem to do is to see the values of the internal "default" (no access modifier) variables. Below are three such variables found in BigInteger.java (lines 2225-2231):
int powersOfTwo = partToSquare.getLowestSetBit();
long bitsToShift = (long)powersOfTwo * exponent;
if (bitsToShift > Integer.MAX_VALUE) {
reportOverflow();
}
int remainingBits;
Any suggestions on how to expose these variables to JDT Debug for learning purposes?

I guess this is not about public vs. non-public but about fields vs. local variables.
Compilation may drop information about local variables, so the debugger no longer has information about their names. In that case a watch expression using that name cannot be resolved. The Variables view should, however, still show the value, albeit with artificial names like arg0 ... You can still correlate the variable to what you see in the source code, as local variables are only added to the Variables view when during stepping you reach the corresponding declaration.

Related

Add local variable to JShell evaluation context

I'm using jdk.jshell.JShell to evaluate Java code programmatically and I'd like to add a local variable to the active evaluation context, so the value is useable in the shell.
I'm instantiating the JShell with a DirectExecutionControl, so it runs on the same JVM as the main code. I've spent quite a lot of time stepping through the source code of the JDK trying to see where I could plug myself, but it's quite opaque; simply getting an Object result out of eval(...) instead of a String required a number of hacks (Oracle, why?).
The answer here seems to suggest that this is not possible, without justification, but I'm too deep into this to accept that.
Ideas I have thought about:
- creating a class dynamically, with a field corresponding to the variable I want to add, and `import static`ing that class into the JShell (but I don't know how to dynamically add an import either)
- trying to find one of the internal auto-generated classes JShell is using to store the variables, and replacing them using arcane reflection magic

Custom compile-time class loading in Eclipse?

Is there a way to hook into the Eclipse compiler to specify custom class reading/resolving/loading logic while a Java source file is being compiled? I'm not sure what the correct term is, but essentially the compile-time equivalent of "class loading" that happens at run-time.
For example, say I have the Java source:
package foo;
import bar.Bar;
public final class Foo {
// getQux() returns type: qux.Qux
private final Bar bar = baz.Baz.getQux().getBar();
[...]
}
The compiler should request that 3 classes are read while compiling the source file foo/Foo.java:
bar.Bar - It is specified as an import.
baz.Baz - It is used in its fully qualified form (... = baz.Baz.getQux()...).
qux.Qux - It is an "indirect" dependency (it is returned by the call to baz.Baz.getQux(), which in turn is used to access a bar.Bar through the call to its getBar() method).
I'd like to be able intercept each of these "class requests" so that I can provide custom logic to obtain the class in question (perhaps it lives in a database, perhaps it it served up by some server somewhere, etc).
Also, I'd like it if no attempt was made to compile any of the source files in the Eclipse project until they are explicitly opened by the user. So in the example above, the 3 class requests (bar.Bar, baz.Baz, qux.Qux) aren't made until the user actually opens the source file foo/Foo.java. Ideally the list of source files in the project needn't be actual files on the filesystem (perhaps they too live in a database, etc) and a compile attempt is made only when a user opens/loads a source file.
I realize that, if possible, this has some drawbacks. For example, if I edit source file foo/Foo.java to make the class "package private", this will silently break any class that depends on foo.Foo until a "full" compile is done of the project. For now, that is fine for my purposes (there are things that I can do later to solve this).
Any ideas/suggestions?
Thank you!
Probably not, this would fall under the Java build path part of the JDT and I don't think it has that level of customization. There does not appear to be a documented extension point for this. To get a definitive answer you would need to look at the source. You could probably add this capability and it would mean that your would need to use an alternate version of the JDT, which might be difficult or impossible.

Writing a custom eclipse debugger

EDIT: There must be some way I can approach this without writing a whole new debugger. I'm currently looking into ways to build on top of the existing java debugger. If anyone has any ideas on how to grab information the Java debugger already has (about stack frames, variables, raw data etc.), that would be really helpful.
--
What I'm trying to do is I have this framework/API built on Java, and I would like to write an eclipse plugin debugger that is customized to my framework. Here is a simple example:
I have two classes, one called scope and one called variable. The scope holds a map of variables. The code is all in java, but I'm using this scope-variable relationship almost like a new language, and would like a variable debug tab that gives me a list of currently active scopes with the variables that are currently stored inside. Here is some code:
import java.util.Hashtable;
public class Scope {
private Hashtable<String, Variable> variableList = new Hashtable<String, Variable>();
// constructor
public Scope(){
}
public void put(String key, Variable v){
variableList.put(key, v);
}
public Variable get(String key){
return variableList.get(key);
}
}
public class Variable {
private String value;
private String name;
public Variable(String aName, String aValue){
name = aName;
value = aValue;
}
public String getValue(){
return value;
}
public String getName(){
return name;
}
public void setValue(String aValue){
value = aValue;
}
}
This is obviously an extremely simple example, but I would like to accomplish something similar to this where I can get a variables window, set a breakpoint, and have a "debugger" list out my active scope objects and the variable objects inside.
I've been trying to read and understand: http://www.eclipse.org/articles/Article-Debugger/how-to.html
and its pretty dense (as well as extremely outdated), but I will try to take some time to understand it. I just wanted to see if anyone had any high level recommendations on how to approach this type of problem, as I have little experience developing plugins in eclipse or making debuggers.
Thanks!
Not an easy task. That article is still the main reference, I think. Old, but not outdated. Try to digest it, and preferably to make it work. Before it, you should have a minimal experience developing Eclipse plugins.
There are many pieces in the picture, but the first thing you must understand is that when Eclipse is debugging something (assuming we are using the standard debug model), we have two separate "worlds": the Eclipse side, and the interpreter side (or, if you prefer, the "local" and "remote" sides).
Int the Eclipse side, the programming involves a cooperation between some Eclipse core classes and some classes of your own, which extend or implement some Eclipse classes/interfaces:
A "launchConfigurationType" (extension point in your plugin.xml) which causes the apparition of a new custom configuration when you click "Debug As -> New Configuration); this goes togetther with some "launchConfigurationTabGroups" definition that defines the "Tabs" dialogs that will appear in your custom launch configuration (eg) (each Tab will have its own class typically).
The launchConfigurationType is typically associated to a LaunchDelegate class, which is sort of your bootstrap class: it has the responsability of creating and starting a running/debugging instance, both on the Eclipse side and on the "interpreter" (or "remote") side.
On the Eclipse side, the running/debugging instance is represented by a IDebugTarget object and its children (the implementation is your responsability); this is created by the LaunchDelegate and "attached" to the remotely running process at launching time.
The remote side, the interpreter or program you are actually debugging, can be anything: a binary executable, a perl script, some app running in a some site (perhaps also a local Java program; but, even in this case, this would probably run in its own JVM, not in the debugging Eclipse JVM!). Your IDebugTarget object must know how to communicate to the "remote interpreter" (eg, by TCP) and perform the typical debugger tasks (place breakpoints, step, run, ask for variables, etc) - but the protocol here is up to you, it's entirely arbitrary.
What is not arbitrary is the hierarchy of your custom classes that the running Eclipse debugger will use: these should have a IDebugTarget as root, and should implement "The debug model" (see figure in article). As said above, the IDebugTarget object is who understands how to make the translation between the EClipse side and the remote side (see this image)
having worked on the eclipse edc debugger, it sounds like writing a whole debugger is not so much what you want.
it sounds like while running the debugger, you will have access to the objects that have the variables and scopes you are interested in.
you can use toString() in the classes themselves or use detail formatters to display a variation on the information you want. the toString() call can get quite detailed and nest into calls, show whole arrays, etc. detail formatters can also be quite complex.
see http://www.robertwloch.net/2012/01/eclipse-tips-tricks-detail-formatter/ . it's the best of several URLs (i have no association with the author).
once you are happy with the output of the Variable and Scope objects, you should be able to add watch expressions that will always show them in your expressions window (thus you don't have to rely on local variables in the stack frame you may be in).
this should then give you the list of Variables and Scopes from your framework that you are tracking … hopefully without having to write an entire eclipse debugger plugin to do so.
ok, i'm going to add a second answer here … i guess i'm not familiar enough with the state of your environment to know why custom detail formatters would not do the trick. for most cases, i think they'll provide you what you're looking for.
but if you're really interested in creating another view holding these items, then you could check out the eclipse jdt project . it's entirely possible that the extension points it provides will give you access to the internal variables and stack-frame information that you're looking to add, and also perhaps some UI that will make your job easier.
in other words, you might not have to write an entirely new debugger plugin, but perhaps a plug-in that can work together with jdt.
the site has pointers to the project plan, source repositories, the bugzilla issue tracking database (used for both bug-tracking and new feature discussion). perhaps some of those who are experts on jdt can help weigh in with their opinions about what will best suit your needs.

How to find static method calls in large Java project?

I'm refactoring some Java code to be more decoupled by changing some static method calls to non-static calls, for example:
// Before:
DAO.doSomething(dataSource, arg1, ..., argN)
// After:
dao.doSomething(arg1, ..., argN)
My problem is that in a large project, it can be hard to find where static method calls are being made. Is there an easy way to do this, either from the command line or in Eclipse?
Such a tool would need to let me ignore "benign" static method calls such as these (either by not finding them in the first place, or by allowing them to be easily deleted from the search results):
String.valueOf(...)
Integer.parseInt(...)
MyClass.someBenignStaticMethod(...)
Some clarifications:
I'm not interested in finding method calls made via reflection
I don't know what static methods currently exist in this project, so it's not as simple as searching for their callers using Eclipse's "Open Call Hierarchy" command (Ctrl-Alt-H), although an easy way to search for non-private static methods would let me use this approach
I'm also interested in finding calls to static methods located outside my project, e.g. javax.mail.Transport#send
I'm looking for a free (as in beer) solution
Do you really need to search? Why not comment out the static method calls one by one? When you compile it then it will flush out the references.
I'd use grep (-R on Linux) to search for initial caps-dot-camel case-open (I don't use it enough to give you the full command line). And then grep -v to get rid of some of the rubbish.
Well, really what I'd do is refactor incrementally. Changes a method, and see what breaks (if nothing breaks, delete the code).
Theoretically you could search through the class files looking for invokestatic. The FindBugs infrastructure would probably help out here (there may be better starting points).
Some IDEs provide support for refactoring. You can refactor every static method one-by-one.
In Eclipse, you can view the call hierarchy to see all the callers of such method. To view the call hierarchy you can select the method name and press Command-Alt-H, or Right-Click on symbol and choose 'Open Call Hierarchy).
We have a product called nWire for Java which might just help. nWire analyzes your code and builds a database of your code components and associations. You can see a brief demo on our web site.
We plan to have reporting capabilities added in the future. In the mean while, if you have some basic experience with databases, you can tap into the nWire repository and, with a simple SQL query, get a list of all your static methods (you can also see the invocations there). nWire uses the H2 database engine which is open-source and free.
I can assist in accessing the database. Drop me a line to support [at] nwiresoftware.com.
I've written a small Java program that uses the excellent ASM library. It lets you exclude packages like java.lang, and produces output that looks like this:
+ java
+ io
- File
# createTempFile(java.lang.String, java.lang.String)
+ javax
+ imageio
- ImageIO
# read(java.io.InputStream)
# write(java.awt.image.RenderedImage, java.lang.String, java.io.File)
+ mail
- Transport
# send(javax.mail.Message)
+ internet
- InternetAddress
# parse(java.lang.String, boolean)
+ xml
+ parsers
- DocumentBuilderFactory
# newInstance()
I'd prefer something that's more easily built into my existing build process, which uses CheckStyle, but this is the best solution I've come up with so far.
A possible solution could be a custom CheckSyle or PMD or ... warning. Currently I have the same challenge and trying it with CheckStyle. It seems to be right easy to write such an extention.

Java Compilation - Is there a way to tell the compiler to ignore parts of my code?

I maintain a Java Swing application.
For backwards compatibility with java 5 (for Apple machines), we maintain two codebases, 1 using features from Java 6, another without those features.
The code is largely the same, except for 3-4 classes that uses Java 6 features.
I wish to just maintain 1 codebase. Is there a way during compilation, to get the Java 5 compiler to 'ignore' some parts of my code?
I do not wish to simply comment/uncomment parts of my code, depending on the version of my java compiler.
The suggestions about using custom class loaders and dynamically commented code are a bit incredulous when it comes to maintenance and the preservation of the sanity of whichever poor soul picks up the project after you shuffle to pastures new.
The solution is easy. Pull the affected classes out into two separate, independent projects - make sure the package names are the same, and just compile into jars that you can then consume in your main project. If you keep the package names the same, and the method signatures the same, no problems - just drop whichever version of the jar you need into your deployment script. I would assume you run separate build scripts or have separate targets in the same script - ant and maven can both easily handle conditionally grabbing files and copying them.
Assuming that the classes have similar functionality with 1.5 vs. 6.0 differences in implementation you could merge them into one class. Then, without editing the source to comment/uncomment, you can rely on the optimization that the compiler always do. If an if expression is always false, the code in the if statement will not be included in the compilation.
You can make a static variable in one of your classes to determine which version you want to run:
public static final boolean COMPILED_IN_JAVA_6 = false;
And then have the affected classes check that static variable and put the different sections of code in a simple if statement
if (VersionUtil.COMPILED_IN_JAVA_6) {
// Java 6 stuff goes here
} else {
// Java 1.5 stuff goes here
}
Then when you want to compile the other version you just have to change that one variable and recompile. It might make the java file larger but it will consolidate your code and eliminate any code duplication that you have. Your editor may complain about unreachable code or whatever but the compiler should blissfully ignore it.
I think the best approach here is probably to use build scripts. You can have all your code in one location, and by choosing which files to include, and which not to include, you can choose what version of your code to compile. Note that this may not help if you need finer-grained control than per file.
You can probably refactor your code so that conditional compile really isn't needed, just conditional classloading. Something like this:
public interface Opener{
public void open(File f);
public static class Util{
public Opener getOpener(){
if(System.getProperty("java.version").beginsWith("1.5")){
return new Java5Opener();
}
try{
return new Java6Opener();
}catch(Throwable t){
return new Java5Opener();
}
}
}
}
This could be a lot of effort depending on how many version-specific pieces of code you have.
Keep one "master" source root that builds under JDK 5. Add a second parallel source root that has to build under JDK 6 or higher. (There should be no overlap, i.e. no classes present in both.) Use an interface to define the entry point between the two, and a tiny bit of reflection.
For example:
---%<--- main/RandomClass.java
// ...
if (...is JDK 6+...) {
try {
JDK6Interface i = (JDK6Interface)
Class.forName("JDK6Impl").newInstance();
i.browseDesktop(...);
} catch (Exception x) {
// fall back...
}
}
---%<--- main/JDK6Interface.java
public interface JDK6Interface {
void browseDesktop(URI uri);
}
---%<--- jdk6/JDK6Impl.java
public class JDK6Impl implements JDK6Interface {
public void browseDesktop(URI uri) {
java.awt.Desktop.getDesktop().browse(uri);
}
}
---%<---
You could configure these as separate projects in an IDE using different JDKs, etc. The point is that the main root can be compiled independently and it is very clear what you can use in which root, whereas if you try to compile different parts of a single root separately it is too easy to accidentally "leak" usage of JDK 6 into the wrong files.
Rather than using Class.forName like this, you can also use some kind of service registration system - java.util.ServiceLoader (if main could use JDK 6 and you wanted optional support for JDK 7!), NetBeans Lookup, Spring, etc. etc.
The same technique can be used to create support for an optional library rather than a newer JDK.
Not really, but there are workarounds. See
http://forums.sun.com/thread.jspa?threadID=154106&messageID=447625
That said, you should stick with at least having one file version for Java 5 and one for Java 6, and include them via a build or make as appropriate. Sticking it all in one big file and trying to get the compiler for 5 to ignore stuff it doesn't understand isn't a good solution.
HTH
-- nikki --
This will make all the Java purists cringe (which is fun, heh heh) but i would use the C preprocessor, put #ifdefs in my source. A makefile, rakefile, or whatever controls your build, would have to run cpp to make a temporary files to feed the compiler. I have no idea if ant could be made to do this.
While stackoverflow looks like it'll be the place for all answers, you could wehn no one's looking mosey on over to http://www.javaranch.com for Java wisdom. I imagine this question has been dealt with there, prolly a long time ago.
It depends on what Java 6 features you want to use. For a simple thing like adding row sorters to JTables, you can actually test at runtime:
private static final double javaVersion =
Double.parseDouble(System.getProperty("java.version").substring(0, 3));
private static final boolean supportsRowSorter =
(javaVersion >= 1.6);
//...
if (supportsRowSorter) {
myTable.setAutoCreateRowSorter(true);
} else {
// not supported
}
This code must be compiled with Java 6, but can be run with any version (no new classes are referenced).
EDIT: to be more correct, it will work with any version since 1.3 (according to this page).
You can do all of your compiling exclusively on Java6 and then use System.getProperty("java.version") to conditionally run either the Java5 or the Java6 code path.
You can have Java6-only code in a class and the class will run fine on Java5 as long as the Java6-only code path is not executed.
This is a trick that is used to write applets that will run on the ancient MSJVM all the way up to brand-new Java Plug-in JVMs.
There is no pre-compiler in Java. Thus, no way to do a #ifdef like in C.
Build scripts would be the best way.
You can get conditional compile, but not very nicely - javac will ignore unreachable code. Thus if you structured your code properly, you can get the compiler to ignore parts of your code. To use this properly, you would also need to pass the correct arguments to javac so it doesn't report unreachable code as errors, and refuse to compile :-)
The public static final solution mentioned above has one additional benefit the author didn't mention--as I understand it, the compiler will recognize it at compile time and compile out any code that is within an if statement that refers to that final variable.
So I think that's the exact solution you were looking for.
A simple solution could be:
Place the divergent classes outside of your normal classpath.
Write a simple custom classloader and install it in main as your default.
For all classes apart from the 5/6 ones the cassloader can defer to its parent (the normal system classloader)
For the 5/6 ones (which should be the only ones that cannot be found by the parent) it can decide which to use via the 'os.name' property or one of your own.
You can use reflection API. put all your 1.5 code in one class and 1.6 api in another. In your ant script create two targets one for 1.5 that won't compile the 1.6 class and one for 1.6 that won't compile the class for 1.5. in your code check your java version and load the appropriate class using reflection that way javac won't complain about missing functions. This is how i can compile my MRJ(Mac Runtime for Java) applications on windows.

Categories

Resources