I’m looking at java bytecode listings and Wikipedia, and they all seem to be basic operations (branch, push, pop, cast, etc.). And many articles use these basic examples. But what happens when I read a line from the console, or create a new JButton? Where’s the bytecode for opening a port?
I believe I saw something for “making a system call” (although I didn’t find it today, skimming through the list several times). Do these “special” calls have their own code, which are directly delegated (don’t know how to say it technically) to the OS by the VM? I know there are ways to open up the bytecode, but I’m looking for a general explanation, not weeks of learning advanced bytecode.
There is no byte code for opening a port or drawing graphics to the screen. There are classes that perform these tasks. These classes have native methods, those are methods written in C (or any other language that can be compiled to a native library) and as they are native, they can access the network and graphcis libraries of your operating system to perform those tasks. So you are instantiating these classes and call some of their methods. Java Byte Code offers byte code for instantiating classes and for calling methods of objects. If the JVM sees that this is a native method, it will call the native code that belongs to this method and this native code can do pretty much anything a C or C++ program could do.
So for example, if you call
System.out.printlnin Java, roughly the following happens:Systemis a class with a static variableout. This variable points to an object of typejava.io.PrintStreamwhich has already been created by the JVM before yourmainmethod is ever executed. Theoutvariable is initialized like this:And the method setOut0 is defined as
This means setOut0 is a native method, written in C, or some other language that can be compiled and linked to a native library, though at least the interface between Java and this library is usually written in C.
Java will search in all loaded libraries for a symbol (in that case symbol means function name) with the name
Java_java_lang_System_setOut0, this isJava_ClassName_MethodNameand call it. A sample C code I have found for this method looked like this:Yet this is not the real magic, the real magic happens elsewhere.
PrintStream.write()callsBufferedWriter.write(). This method again callsOutputStreamWriter.write()(not directly, but sooner or later it ends up there) and this method callsStreamEncoder.write(). Wow, it’s getting hard to trace that call. TheStreamEncodercallsBufferedOutputStream.write(), this one callsFileOutputStream.write()and this one callsFileOutputStream.writeBytes()and finally, finally we are there!FileOutputStream.writeBytes()is a native method. It will look something like this:So it calls a function named writeBytes and this function looks different depending on your operating system, e.g. whether this is Windows, Linux or OS X. On UNIX/Linux systems this function may call another function (and so on), but somewhere is a simple C function call to write something to a C
FILE *stream or a file descriptor (which is just anintin C). So it could be aprintf()/fprintf()or aputs()/fputs()call that writes tostdoutor awrite()call that writes toSTDOUT_FILENO. In Windows it is usually a call toWriteFile(), though it could also be aprintf()/fprintf()(those are C standard functions, all platforms must support them).