javap -l option cannot display line number info - java

The javap command has several options, one of them is -l, which can print line number and local variable tables. Suppose a java program has been compiled successfully and there is the file "Main.class", so running javap -l Main can produce something like:
public static void main(java.lang.String[]);
LineNumberTable:
line 100: 0
line 101: 27
line 275: 54
LocalVariableTable:
Start Length Slot Name Signature
0 55 0 args [Ljava/lang/String;
However, I'm using this javap -l xxx command on the class files of one java program, but the area of line number and local variable table is empty (which shouldn't be). The javap command and other options such as -s, -verbose works fine, but only the line info area corresponding to the -l option is empty.
Has anyone ever encountered such weird case?

Use -g to compile your code, otherwise the line numbers are not kept (akin to the stack trace displaying "compiled code" instead of the line number)

Related

Call external programs in Scala

I am encountering a problem of calling an external program (especially, a SAT solver Picosat) from a Scala program.
Specifically, the problem is that the system returns "java.lang.RuntimeException" with "Nonzero exit value: -1073741515" when calling Picosat from ScalaIDE, although the system works when calling it from a (Cygwin) terminal.
As an example, a minimal code example of this problem is follows:
import sys.process._
object Hello {
def main(args: Array[String]): Unit = {
val result = "picosat -h".!!
println(result)
}
}
The executing this sample code returns the following exception message and just exits, when executing the sample code from ScalaIDE:
Exception in thread "main" java.lang.RuntimeException: Nonzero exit value: -1073741515
at scala.sys.package$.error(package.scala:27)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.slurp(ProcessBuilderImpl.scala:132)
at scala.sys.process.ProcessBuilderImpl$AbstractBuilder.$bang$bang(ProcessBuilderImpl.scala:102)
at Hello$.main(Hello.scala:5)
at Hello.main(Hello.scala)
although it prints correct "help message" of Picosat when executing the sample code from Cygwin as follows:
> scala src/Hello.scala
usage: picosat [ <option> ... ] [ <input> ]
where <option> is one of the following
-h print this command line option summary and exit
--version print version and exit
--config print build configuration and exit
-v enable verbose output
-f ignore invalid header
-n do not print satisfying assignment
-p print formula in DIMACS format and exit
--plain disable preprocessing (failed literal probing)
-a <lit> start with an assumption
...
I am grateful if you could provide any clues for this problem?

Batch script - unexpected at this time error

Below is my script where I run "test.bat 1" command in command prompt,
1 is taken as input by my java program and it returns incrementing 1 i.e 2.
This should go on until the value is 10.
Following is my batch script.
#echo off
set "java_output="
setlocal enableDelayedExpansion
:top
for /f "delims=" %%J in ('java -jar test.jar %*') do (
set "java_output=!java_output! %%J"
)
set java_output=%java_output%
echo %java_output%
if %java_output% NEQ 10 goto top
endlocal
and below is my java code in jar.
public class Test {
public static void main(String[] args)
{
System.out.println(args[0]);
int ret = Integer.parseInt(args[0]);
System.out.println(ret+1);
}
}
The following is the output that I am getting.
C:>test.bat 1
1 2
2 was unexpected at this time.
Can anyone tell me whats the issue.
Since your output in java_output is 1 2 (as displayed) then the if statement becomes
if 1 2 neq 10 ...
if expects if string1 op string2 ... and sees 2 as the comparison operator which must be one of ==, equ, neq, lss. leq, gtr, geq
Since you are stringing numerics together with spaces, it's extremely unlikely ever to be anything other than not-equal to 10.
Given response:
set "java_output=!java_output! %%J"
)
set java_output=%java_output%
should be
set /a java_output=%%J"
)
The
set java_output=%java_output%
line does nothing and is redundant.
set /a assigns a numeric value or arithmetic expression.

Heredoc for Java from bash command line

As a JAVA teaching assistant, I get stuck with grading a lot of student's labs. A lot of these labs use a Scanner to get input from a user. Instead of repeated bashing numbers into the keyboard, is there a way I can utilize a heredoc to run all of the labs with the same input parameters without changing the student's code? What I have so far (which works for except the heredoc-esque code):
#!/bin/bash
for i in unzip/*; do
echo $i
javac $i/lab0/AddThree.java
cd $i/lab0
java AddThree <<EOF
2
3
4
EOF
cd ../../..
done
The code I'm trying to grade adds three integers that are provided by the user. unzip is the directory where each student has a folder (i.e. file structure is ./unzip/student/lab0/sourcecode.java)
Java gives:
unzip/student
Hello out there
I will add three numbers for you
Enter three whole numbers on a line :
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:909)
at java.util.Scanner.next(Scanner.java:1530)
at java.util.Scanner.nextInt(Scanner.java:2160)
at java.util.Scanner.nextInt(Scanner.java:2119)
at AddThree.main(AddThree.java:10)
./lab0test: line 9: 2: command not found
./lab0test: line 10: 3: command not found
./lab0test: line 11: 4: command not found
./lab0test: line 12: EOF: command not found
Your heredoc looks good except it will send the spaces at the start of each line. To get rid of those, you can either use -EOF and start each line of the heredoc with Tab characters, which will get stripped:
cd $i/lab0
java AddThree <<-EOF
TabTab2
TabTab3
TabTab4
TabTabEOF
cd ../../..
Or unindent the heredoc contents. It's ugly, but it'll work.
cd $i/lab0
java AddThree <<EOF
2
3
4
EOF
cd ../../..
Alternatively, if the input is short enough you could do it inline:
java AddThree <<< $'2\n3\n4'
(Using $'...' tells the shell to interpret \n escape sequences.)

ksh command subsitution with quotes into array

I have a Java class with the following output:
"Roses are red" "Violets are blue" "Daisies are white"
I am trying to create a KornShell (ksh) script that executes this Java class, stores the result into an array, and then outputs
Roses are red
Violets are blue
Daises are white
This is my first attempt at the script:
1 #!/bin/ksh
2
3 set -A colors $(java Colors)
4
5 for i in "${colors[#]}"
6 do
7 echo "$i"
8 done
However, the output looks like this:
"Roses
are
Red"
"Violets
are
blue"
"Daisies
are
white"
When I throw:
echo set -A colors $(java Colors)
into the script to see what is being called, it returns:
set -A colors "Roses are Red" "Violets are blue" "Daisies are white"
If I replace that exact output with line 3 from above, I get the desired output:
Roses are red
Violets are blue
Daises are white
Why does the command substitution throw the whole thing off?
Below is the Java class if that helps:
public class Colors {
public static void main(String[] args) {
System.out.println("\"Roses are Red\" \"Violets are blue\" \"Daisies are white\"");
}
}
So I ended up making it work by throwing an 'eval' in front of the set command. It looked like this:
1 #!/bin/ksh
2
3 eval set -A colors $(java Colors)
4
5 for i in "${colors[#]}"
6 do
7 echo "$i"
8 done
I'm not sure why that worked exactly, but it did.
You may use quotes on $( ) :
set -A colors "$(java Colors)"
to avoid word splitting
pass the output of your java command as arguments to another shell script.
Then it will give $1=>"Roses are red",$2=>"Violets are blue", and so on.
you can get hold of all the input arguments using $#
This sort of thing is distressingly hard to do. This seems to work:
$ cat roses
echo '"Roses are red" "Violets are blue" "Daisies are white"'
$ IFS='
> '
$ set -A colors $(eval printf '%s\\n' $(./roses))
$ printf "%s\n" "${colors[#]}"
Roses are red
Violets are blue
Daisies are white
$
The script ./roses does the same job as your Java class. The variable IFS is the inter-field separator string; it is set to a newline (only). The set line creates an array colors. The value is what you get from executing and capturing eval printf '%s\\n' $(./roses). The second printf statement prints the elements of the array one per line.
Tested with ksh on Mac OS X 10.8.4.
An equivalent in bash is:
$ IFS='
> '
$ colors=($(eval printf '%s\\n' $(./roses)))
$ printf "%s\n" "${colors[#]}"
Roses are red
Violets are blue
Daisies are white
$
Depending a bit on the version of bash, there are probably other ways to do it too.
You should save and restore the value of $IFS before trampling it.
$ old_ifs="$IFS"
$ IFS='
> '
$ ...use the modified value...
$ IFS="$old_ifs"
$

hprof profiler output doesn't include line numbers regardless of `lineno` value

I'm running
java -cp some:jars:out \
-agentlib:hprof=cpu=times,format=a,file=java.hprof.txt,lineno=y,doe=y com.foo.Benchmark \
< /dev/null
and in the output I get stack frames without line numbers
THREAD START (obj=50000150, id = 200002, name="HPROF gc_finish watcher", group="system")
THREAD START (obj=50000151, id = 200001, name="main", group="main")
THREAD START (obj=50000281, id = 200003, name="Thread-1", group="main")
THREAD END (id = 200003)
THREAD END (id = 200001)
THREAD START (obj=500002a5, id = 200004, name="DestroyJavaVM", group="main")
THREAD END (id = 200004)
TRACE 307081:
com.foo.Benchmark.methodName(Benchmark.java:Unknown line)
com.foo.Benchmark.anotherMethodName(Benchmark.java:Unknown line)
...
If I change lineno=y to lineno=n I still get Unknown line.
I compiled the classes with -g. My javac looks like
javac -g -Xlint -encoding UTF-8 -source 1.5 -d out -classpath ... src/main/com/foo/*.java
I checked the .class files to make sure they have line numbers:
javap -classpath out -c -l com.foo.Benchmark
shows plenty of things like
LineNumberTable:
line 1077: 0
line 1078: 8
line 1079: 14
line 1080: 21
line 1082: 23
line 1083: 31
line 1084: 43
Am I using some flag combination that prevents line number output?
I faced exactly the same problem, but compiling the source with -g helped. After compiling with -g, I see the line numbers like this (which I don't see otherwise, without -g option) -
LineNumberTable:
line 16: 0
line 17: 8
line 18: 12
line 19: 20
line 18: 29
line 21: 35
Now, if I run this -
java -cp "./build/classes" -agentlib:hprof=heap=sites,depth=20 org.sample.welcome.Main a b c
I do get the line numbers for the user-defined classes. Even though I am not sure what's going wrong in your case, these are my observations -
Using javac without -g: If I have -lineno (default y) set to y, I still don't see the line numbers for most of the classes except for the user-defined classes (Main in the above case). If I've set -lineno to n, then I won't see line numbers for any of the classes anyway.
Using javac with -g: If I have -lineno set to y, I can see the line numbers for all the classes (not sure what's going wrong in your case).
The only documentation I could find for HPROF doesn't say anything beyond this. I think one option would be to try with fewer optional arguments and see the results.
Note: I'm using JDK 1.6 in the above example

Categories

Resources