Log line numbers of executed java code - java

I am writing part of a PHP web application (which will be used in a high school bug finding contest) where the user must find bugs in a given Java program. As a part of this, when the Java program executes, we want to highlight the lines of the source of the Java program where the code has executed. To do this, all we need are the line numbers of the source that have been executed, that is, the code path (or is it called code coverage?). We will highlight the lines in the source file using the line numbers.
We will be using PHP's shell-exec() to execute the Java program and the tool to get the code path (whatever that will be). What is the easiest way of getting the line numbers of code path?
Thank you very much!
Here is a picture that describes what we would like

PHP interperts the code, which means it runs over the source each time you run the program. This has the benefit of blowing up as the code is read (which makes line number printouts trivial); however, it often is expensive in other ways, as you cannot optimize deeply (or do any pre-runtime error checking).
Java compiles its code into a JVM assembly language called "bytecode." This means that what is running doesn't generally have access to (or even use) the source code. That said, there are techniques. A compiled Java class has the ability to add "extra data" and one of those "extra data elements" is a line number table, which is an index allowing someone running the assembly to "look up" the line number as the compiler recorded it.
This generally works ok, with the considerations that: compilers often don't mark up every instruction, the source code may not be available, optimization might make certain inner chunks of code not function in ways that facilitate pointing to the input code text.
How code coverage tools "fix" this is that they generally insert into the code (at the assembly level) a large number of commands that effectively act as logging statements to a format that allows the tool to determine which path through the code was actually followed. This is then mapped back through the line number table as best as possible and then used to highlight lines within the original source file.
If you want something with finer resolution (something that can process which portion of a line was executed) then you need to dig deeper. Eventually you might even consider writing your own compiler (or compiler extension) which will store your own custom line number table that overcomes the shortcomings of the current solutions.
Tricks like throwing exceptions (as Shiven has mentioned) and parsing out the line number do work; however, they pollute your code with odd exception processing for items that really aren't exceptional, just to "get the line number". Due to the code clutter and the generally poorer runtime performance of exceptions, I tend to avoid such solutions (but they do work).
Anyway, hopefully this will give you a view as to why it doesn't always work exactly the same way as PHP.

You could get a linenumber if you compile the program with the -g option, do a printStackTrace(), capture the trace output and extract the linenumber from there.

Take a look at Cobertura. It computes coverage and stuff like that, and if it doesn't already do it, it should be relatively easy to add the line number collecting to it.
There's a very hackish attempt to do that, but that's so slow that you may not be able to use it in production https://bitbucket.org/jowu/myriapod/wiki/Home

I have never done or seen anything like this but it does seem like an interesting problem. My thought would be to use the java debugger (jdb) to run the code, rather than just the java command.
You can step through the code line by line (via the step command in jdb) and each time a line executes its line number is spit out. This would require a little help from the PHP side (it would have to parse the line number as well as execute the next step command) but the line numbers are there. Here is a sample output from a very basic java program.
Java (TestClass.java)
public class TestClass {
public static void main(String[] args) {
System.out.println("foo");
System.out.println("bar");
}
}
jdb (jdb TestClass after running javac TestClass.java)
Initializing jdb ...
> stop at TestClass:3
Deferring breakpoint TestClass:3.
It will be set after the class is loaded.
> run
run TestClass
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
>
VM Started: Set deferred breakpoint TestClass:3
Breakpoint hit: "thread=main", TestClass.main(), line=3 bci=0
3 System.out.println("foo");
main[1] step
> foo
Step completed: "thread=main", TestClass.main(), line=4 bci=8
4 System.out.println("bar");
main[1] step
> bar
Step completed: "thread=main", TestClass.main(), line=5 bci=16
5 }
main[1] step
>
The application exited

Try referring to this link JVMDI
You can try accessing the values of the program counter and then map it onto the lineNumberTable .
OR
I think JVMDI has a method which can access the line number of the executing code.I'm not sure of the latter,refer the to the link above and hope it helps.

Related

Start coding from the debugging point Eclipse

I have a code like this
String s="Test-Code-Data";
String[] splitedData = s.split("-");
I have a break point at second line. When my code reaches that point, can i start coding below that and immediately see the output. For example. I want to see the output from below code, and i type it when the execution reaches the second line only.
System.out.println(splitedData[1])
Is this possible in eclipse?
To answer your question, NO you cannot effectively alter code while the code is in execution without making Eclipse warn you that the code is 'out of sync'.
However, you can look at the actual values of your various variables in the various stages of execution of your code. And, once the execution is complete, then you can edit the code and Run the program in Debug again and keep going that way.
You can use the Inspect Variable feature to look at the value of a variable while in execution and paused at a breakpoint by selecting the variable you'd like to inspect and using the keyboard shortcut Ctrl+Shift+I to get the value of the variable.

Is there any way that Java could get current file name and current line number?

In C++, the file of the source code and current line number is decided by FILE and INLINE, which is decided at compiling time, is there any method in Java that could do the similar thing? The file and line number is decided at compiling time instead of runtime? this will be convenient for log. I kind of doubt that use runtime method to detect these information will decrease the performance.
You could use Thread.getStackTrace() and something like
System.out.println(Thread.currentThread().getStackTrace()[1]);
Output includes the current method and line number (if debugging was compiled in).
For example,
com.stackoverflow.Main.main(Main.java:23)

How can I access the Eclipse Java debugger from a plug-in?

I'm developing a plug-in for the Eclipse platform. This plug-in will be used to give information about the line of Java source code currently being debugged.
When debugging a Java program, as you hit a breakpoint, Eclipse switches to the standard Debug perspective. Inside this perspective, apart from the standard Console output, the stack trace and various other views, you can see source code of the Java program currently being debugged. Inside this 'source code view', you can see a highlighted line, which is the line of code currently being debugged/evaluated. This highlighted line of code is what I want to access.
Assuming I know when the debugger is running (I assess that through a DebugBreakpointListener class that implements IJavaBreakpointListener), I need to 'ask questions' to the debugger. What, I imagine, I will need, is to somehow ask the debugger directly either for the line of code it is currently highlighting/debugging/evaluating or for the line number of the said line of code.
I'm making a static access to the JDIDebugModel to add the Java Breakpoint Listener:
JDIDebugModel.addJavaBreakpointListener(new DebugBreakpointListener);
I thought I could access the debugger with static references to JDIDebugPlugin but I've yet to find what I'm looking for.
At Part 3 of this research paper, the authors suggested that:
The Eclipse Java debugger is built upon the API of Java Debug Interface (JDI), which is part of the Java Development Toolkit. This API enables adding requests to monitor JVM events such as BreakpointEvent. When an event occurs, the debugger gets a notification and the thread in which this event took place can be obtained. For each frame in the stack trace of this thread the following information can be obtained:
• The source Java file in which the execution at this frame has taken place (or null if the source is not available).
• The method and line number (if available).
• The this object or null if the method is static.
The Eclipse debugger uses this information when a breakpoint is hit. It shows the stack trace for the suspended thread in the ”Debug” view. For the selected frame in this trace, Eclipse highlights the corresponding line number in its source file, and displays the this variable in the ”Variables” view.
This bulletpoint-listed things are exactly what I'm looking for.
Unfortunately, I can't find detailed documentation on how to 'plug in' to the debugger.
If someone can give me information, point me to information or a sample code, or maybe provide me with contact information of someone from the Eclipse JDI project, it would be immensely appreciated.
Thanks in advance.
------Update & Answer:------
With the help of greg-449's answer, I did exactly what I wanted to do. Here's what I did:
The aformentioned breakpoint listener I wrote implements the interface method breakpointHit, which is as follows:
#Override
public int breakpointHit(IJavaThread thread, IJavaBreakpoint breakpoint) {
System.out.println("Just hit a breakpoint!");
// Save pointers to the thread & breakpoint for future use.
return 0;
}
With the pointers to the thread and breakpoint objects saved in one of my objects, I could query them to get up-to-date information on the state of the frame stack, the thread and about the particular breakpoint that I've hit. I can get the namea dn path of the class the debugger is currently debugging by calling:
IStackFrame topStackFrame = thread.getTopStackFrame();
int debuggedLineNumber = topStackFrame.getLineNumber();
String debuggedClassPath = topStackFrame.getLaunch().getSourceLocator().getSourceElement(thread.getTopStackFrame()).toString();
This was exactly what I was looking for. I imagine I will need to read the source code files manually, run them through a tokenizer by having the 'newline' character as a delimiter and get the corresponding token to read that specific line.
There is a huge amount of information available in the IJavaThread and IJavaBreakpoint arguments passed to the breakpointHit method of the IJavaBreakpointListener which should contain this information.
I think for breakpoints which have a line number (not all do) the IJavaBreakpoint argument also implements ILineBreakpoint containing the line information.

Java interpreter code at runtime

We have discussed how java is first compiled into Java bytecode and then interpreted by the JVM. Build into the program we are using (Dr Java), there is a panel called Interactions where you can type code in real time and have it be interpreted and ran (I believe that is how it works). I was wondering if it was possible to have a compiled program in java be ran, and then allow a user to input java code to be interpreted to modify the things that happen. I can't really think of any practical uses of this, but here is an example to clarify:
User runs a program and an integer in initialized with the value of 2 and the name of changeNumber. A pop-up comes up allowing the user to input some java code. They can input something like - "changeNumber = changeNumber + 2;" and have the code execute in real time where if you ended up printing out changeNumber, you would get 4.
This is possible using the Reflection API.
As a side note, I do not understand the downvotes. This is a good and well-written question for a beginner.

Faster or cleaner way to find out if a package is installed on Android

I know that I can either catch the NameNotFoundException from a call to PackageManager.getPackageInfo or loop through the PackageInfo list returned by PackageManager.getInstalledPackages to know whether a particular package is installed, but both of these seem either long winded or ugly. On my personal phone, I have more than 300 packages installed, so I'd hate to have to do that operation every time I need to check. And catching an exception as a means of performing application logic just makes me feel wrong all over. Am I missing the isPackageInstalled method somewhere, or do I just need to implement it myself using one of the above mentioned techniques? And if the latter, which would be considered the faster and less resource intensive option?
Since PackageManager.getInstalledPackages() returns a List, you don't need to loop through it manually. You can use List.contains() or List.containsAll() to accomplish the task in one line of code. Of course, this doesn't change the efficiency since both methods likely contain a loop themselves.
If using the API really bugs you then you might look into a hack involving the following
Bash shell expression that gets the PM list
Java Runtime expression
Java Pipes and buffers and streams
Java NIO
Java grep
So the bash expression would be :
pm list packages -f | sed 's/^package.//' | awk -F"=" ' { print $2" "$1 } ' | sort
and of list of references for handling stdout from the 'pm list' in a way that might wind up being faster...
PipedBuffers
NIO/grep
Runtime/streams
Handling a NameNotFoundExcepetion should not make you feel "wrong all over" IMHO. According to the documentation this exception will be thrown if the package does not exist since api level 1. Using try/catch statement is very similar to using an if/then statement to test for a null value.
In this case it should not be considered a workaround or a hack as you are using the documented and expected return value of an exception to determine if a package exists.
I would assume this method to be faster than iterating through the List returned by getInstalledPackages(). However, I don't know what steps android takes prior to returning a NameNotFoundExcepetion. This would make an interesting benchmark test.
I'm not aware of any other practical method to test for an installed package.
I wrote some benchmarks and tested catching the exception vs a few different ways of fetching the installed packages and looping through them. Here is my result
Calling PackageManager.getPackageInfo and catching the NameNotFoundException took between 1 and 4 ms in all cases whether the requested package was installed or not, and I made sure to also include cases where this was the first call to the PackageManager for a particular run of the app and as a subsequent call just in case the framework does any caching of this information per app launch.
Calling PackageManger.getPackageInfo took between 1 and 1.5 seconds in all cases as well.
Calling getPackageInfo and catching the exception to determine if the package isn't installed is by far the faster way to check.

Categories

Resources