I'm looking for a tool for debugging and stepping through Java Bytecode, with
visualizing of the basic JVM state, including the operand stack and the local variables array, merely for educational purposes and JVM learning (for myself, and hopefully for others as well). Is there such a tool at hand?
I came across the Bytecode Visualizer Eclipse plugin by Dr. Garbage, which allows breaking on and stepping through Bytecode, but it doesn't visualize the JVM state:
http://www.drgarbage.com/bytecode-visualizer
The following related questions (quite old) mention a few tools, some of which allow stepping through Bytecode, but none with JVM state visualization:
Are there any JVM simulators / bytecode execution visualizers?
Is there a disassembler + debugger for java (ala OllyDbg / SoftICE for assembler)?
Java debugging with byte codes
Is there such a tool at hand, that is capable of debugging simple Java programs? Or even a simple JVM simulator?
Thanks!
I've adapted the PyJVM to do what you are after. It shows a simple gui for each thread of the Java program (they have to be compiled for Java7).
The only issue with this tool is that it doesn't have a GC, since garbage collection is handled by Python itself. Therefore, the Thread 1 (daemon) (the reference handler) will not ever do anything. Finalize method also won't trigger.
Source is available on https://github.com/MatevzFa/pyjvm (warning: the source code isn't very nice to look at), you can also install it with pip (pip2 actually, since PyJVM is written in Python2).
Install:
pip install pyjvmgui
Upgrade:
pip install pyjvmgui --upgrade --no-deps
I stil have to write a good README for it.
Related
I have simple java programm that will just print Hello World.Can it be possible to print without using JVM installed in a machine ?But compiler is there.
You can compile Java Byte Code to Machine Code using something like this:
http://en.wikipedia.org/wiki/GNU_Compiler_for_Java
Or you can use any of the MANY Java to C/C++ converters out there to make a C/C++ version, and compile that. (Search Google for "Java C Converter")
Warning: I have never tried any of these, including the linked GNU Compiler, so I cannot make any attestations to their usefulness or quality.
#SplinterReality already pointed you to some compilers (googling "java bytecode to native code compiler" will show you some more options).
I will just expand on that seeing some people are a bit confused:
The JVM is a program that takes java bytecode, which you get by running javac on your java source code (or you generate it in some other fashion). Bytecode is just a set of instructions that the JVM understands, it's there to give you a consistent set of opcodes which are platform independent. It's the JVM's job to then map those opcodes to native instructions, that's why JVMs are platform dependent. That's why when you compile your java source code to java bytecode you can run it on every platform.
That's why, whether you have java source or bytecode, you can take it and just compile it directly to native code (platform dependent, actually sometimes that's exactly what the JVM, and to be more precise the JIT, does - it compiles stuff to native code when it sees the need to). Still there's more to the JVM than just bytecode interpretation - for instance you need to take care of garbage collection.
So the answer is: yes, but do you really want to do it? Unless you want to be running it on some embedded systems I don't really see any reason to.
Yees, it is possible to run a java program without a JVM, albeit with limitations. Aside from the http://en.wikipedia.org/wiki/GNU_Compiler_for_Java , there is the GraalVM native-image generator, which could be used : https://www.graalvm.org.
If that program is a one file source code (not compiled in bytecode) then you can ;)
Here or here. Here will be fine as well ;)
Just put it there and press compile and run.
But it will work only with simple stuff only, and you have to have source code.
I would not be surprised if there would be a site that would allowed to upload class from users PC
I was wondering, is it possible to get eyes on the actual machine code that the HotSpot compiler generates when it compiles a given Java bytecode class or method?
Yes, with -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly the Hotspot VM can give you that information when it actually executes (compiles) a given bytecode method.
See for example HotSpotInternals Wiki:Print Assembly for details. It does require a disassembler module (hsdis-*.dll on Windows).
A bit more comfortable is using JITWatch (but it uses the same infrastructure from HotSpot).
I was recently comparing the JVM and CLR platforms and was discussing the impact of JIT compilation. The discussion I was having led to .NET's ability to precompile code using the NGen tool, which would eliminate the need for JIT compilation. Is there an equivalent in the Java platform?
The native compiler that I've heard the most about is Excelsior JET - Java Virtual Machine and Native Compiler. See http://www.excelsior-usa.com/jet.html for more details. Basically you can turn your project into a single executable without the hassles of the usual Java packaging.
They have been around for a long time (they where here when I joined the Java ranks in 2001 and they are here now. I just heard a week ago how a company is using their solution are and are happy with it.
About couple of years ago at JavaONE I also met a developer or two of the product and they told me that they are live and kicking and doing well.
I'm not aware of any, personally (you can look at options like launch4j, jexe, etc, they are just wrappers, not like NGen), and I'm not sure how feasible it would be... The answer to this question goes into some details on the subject of compiling to native code: Differences in JIT between Java and .Net
Yes. As of Java 9, you can. The feature you are looking for is called Ahead of Time (AOT) compilation.
There are two main JVMs in use today:
HotSpot (and it's variants), which is the main JVM from Oracle.
OpenJ9, originally from IBM.
OpenJ9
In OpenJ9, just run the Java Virtual Machine with the -Xshareclasses:persistent option. This causes the VM to store compiled binaries into a cache, which persists across system boots. It does not force the Java VM to use the precompiled code in all cases, as in many cases Just In Time (JIT) code can execute faster. The JVM will pick whether to use the cached binary or not on a case by case basis. When a cached AOT method is run it might also be optimized further by the Just-In-Time (JIT) compiler.
Full details are available at:
https://www.eclipse.org/openj9/docs/aot/
https://www.eclipse.org/openj9/docs/xshareclasses
HotSpot (OpenJDK)
The HotSpot (OpenJDK) builds now include an experimental VM that can completely precompile everything, called GraalVM. You manually create native binaries using the jaotc executable. Note: this is currently only available on Linux (and possibly Mac) systems.
Details on how to use the jaotc compiler are at:
https://docs.oracle.com/javase/10/vm/java-hotspot-virtual-machine-performance-enhancements.htm#JSJVM-GUID-F33D8BD0-5C4A-4CE8-8259-FD9D73C7C7C6
https://openjdk.java.net/jeps/295 (this includes an example where you generate and use an AOT library for the java.base module).
Note: jaotc is not as simple to use as the OpenJ9 shared classes flag.
How could I have a breakpoint in Java that's triggered when a native method calls (directly or indirectly) a certain Linux syscall?
This is not quite a breakpoint, but at least it gives you a stack trace, which may be all you need. Furthermore, the Systemtap language does allow you to do more stuff than just print stack traces, if you need to.
In the IcedTea JVM source code, you will find a SystemTap file with functions that can be used to get stack traces from a running IcedTea (with Hotspot) JVM. As I understand it, with these functions you can get a Java stack trace from any event that SystemTap supports - even from in-kernel events.
Note that despite having the same name, these jstack functions are unrelated to the jstack(1) command-line utility supplied with the JDK. They work via memory inspection, not via calling back to the JVM, so they are quite specific to Hotspot internals, and therefore probably won't work with non-Hotspot-based JVMs.
Note: Systemtap does not fully work on default Debian kernels, so you may need to compile your own kernel on Debian-based systems. This problem does not affect Fedora or Red Hat.
In theory, it would be possible to native-compile the application using an ahead-of-time (AOT) compiler for Java, and then use a native debugger to set a breakpoint or catchpoint on the syscall. (Bonus: You then get a complete stack trace including all the C functions called by the native method, and the ability to debug those C functions seamlessly.)
You would probably want to use a debugger which knew how to demangle names produced by the AOT compiler. For example, gdb knows how to demangle names produced by gcj, so a gcj combination with gdb should work.
The trouble with this combination is that gcj is still stuck at partial JDK 1.5 compatibility, and no-one has bothered to do the work of merging in the OpenJDK class library (it was suggested on the gcj mailing list in 2009). And as a result, gcj has never been a popular option - people do often use it unintentionally (particularly on Debian and Ubuntu), but then when they hit a problem they tend to switch to a more standard JDK instead of reporting a bug.
Native compilation with an AOT compiler is also much slower than just letting the JRE JIT-compile code when it thinks it's necessary.
I was briefly reading about Maxine which is an open source JVM implementation that written in Java. This sounds circular to me. If java requires a virtual machine to run in, how can the virtual machine itself be written in Java (won't the VM code require a VM in which to run, and so on?).
Edit: Ok, so I see I overlooked the fact that Java doesn't have to run in a VM. How then does one explain how a LISP compiler can be written in LISP? Or should this be a new question altogether?
Your assumption that Java requires a virtual machine is incorrect to begin with. Check out the project GCJ: The GNU Compiler for the Java Programming Language.
You are asking about the chicken and the egg.
Read: http://en.wikipedia.org/wiki/Bootstrapping_%28compilers%29
The JVM that you need to bootstrap a JVM written in Java probably does not need a lot of features (such as garbage collection and JIT), could be very simple. All the more advanced features could then be implemented in Java (which seems to be exactly the point of Maxine, to experiment with new ideas in JVM technology).
Also, Maxine does contain C code, which I guess makes up a minimal runtime environment that is used to get the rest of Maxine going. I take it that the interesting bits (JIT compiler, garbage collection) are then completely implemented in Java.
See bootstrapping.
Java code can be compiled directly to machine code so that a virtual machine is not needed.
I had a look at Maxine last week and was wondering the same :)
From the Maxine documentation:
1 Building the boot image
Now let's build a [boot image]. In
this step, Maxine runs on a host JVM
to configure a prototype, then
compiles its own code and data to
create an executable program for the
target platform.
2 Running Maxine
Now that Maxine has compiled itself,
we can run it as a standard Java VM.
The max vm command handles the details
of class and library paths and
provides an interface similar to the
standard java launcher command.
You can have a look at the well-established method of bootstrapping compilers. I think it started in the 70s...
It is kinda 'whooaoaa man, how can that work???' - but I think you are describing the phenomenon known as 'self-hosting':
Languages (or toolchains/platforms) don't start out as self-hosting - they start off life having been built on an existing platform: at a certain point they become functional enough to allow programs to be written which understand the syntax which it itself happens to be written in.
There is a great example in the classic AWK book, which introduces an AWK program which can parse (a cut-down version as it happens) other AWK programs: see link below.
There is another example in the book "Beautiful Code" which has a Javascript program which can parse Javascript.
I think the thing to remember on this - if you have (say) a JVM written in Java which can therefore run Java Byte code: the JVM which runs the Java JVM itself has to be hosted natively (perhaps this JVM was written in 'C' and then compiled to machine code) : this is true in any case of a self-hosting program eventually - somewhere along the line.
So the mystery is removed - because at some point, there is a native machine-code program running below everything.
It kinda of equivalent of being able to describe the English (etc) language using the English language itself....maybe...
http://www.amazon.co.uk/AWK-Programming-Language-Alfred-Aho/dp/020107981X/ref=sr_1_fkmr0_3?ie=UTF8&qid=1266397076&sr=8-3-fkmr0
http://www.amazon.co.uk/gp/search/ref=a9_sc_1?rh=i%3Astripbooks%2Ck%3Abeautiful+code&keywords=beautiful+code&ie=UTF8&qid=1266397435
http://en.wikipedia.org/wiki/Self-hosting
I know this post is old but I thought I might add a little to the discussion as they are points that have been missed. So future readers may find this helpful.
I wonder if everyone is missing the point here. You can write most any kind of compiler, interpreter, or virtual machine in almost any language. When using C to write a C compiler a C compiler is needed to compile the new compiler. However, the output is native code that runs on the designated platform. Just because the JVM is written in the language that runs on the JVM doesn't mean the output must result in code that runs on the JVM. For instance you can write C, Basic, Pascal Compilers or even assemblers in Java. In this case you will need the JVM to create the compiler or assembler but once created you may no longer need the JVM if the initial code resulted in native code. Another approach is to write a translator that takes an input language and converts it to a native machine language so that you write your program in language A which compiles into language B which which is then compiled into machine code. In the micro controller world you see this a lot. Someone wants to write programs in Basic or Java so they write the Basic/Java compiler to produce C code for an existing C compiler. Then the resultant C code is compiled into machine language providing the native Basic/Java compiler. This approach is usually easier than writing the Basic/Java compiler directly in machine code.
Many years ago I wrote BasicA and GWBasic programs that produced assembly code to 6800 and Z80 micros. My point is that the output need not be of the same ilk as the input or target. I.E. Just because you're writing a JVM in Java doesn't mean the final result must be ran under a Java JVM.
Here is a good paper on bootstraping a self-hosted VM. It's not Java, but javascript, but the principles are the same.
Bootstrapping a self-hosted research virtual machine for JavaScript: an experience report
Note that while bootstraping a self-host compiler and bootstraping a self-hosted VM are somewhat similar, I believe they do not raise the exact same challenges.