01 Discussing Your Understanding of the Java Platform

01 Discussing your understanding of the Java platform #

Since you started working with Java development until now, what is your most direct impression of Java? Is it its widely promoted “Write once, run anywhere” feature, or is it the somewhat formalistic syntax that it has developed over time? How well do you actually understand the Java platform? Please take a moment to pause and reflect on this.

The question I want to ask you today is: What is your understanding of the Java platform? Is the statement “Java is interpreted” correct?

Typical Answer #

Java itself is an object-oriented language, with two notable features. First, it is known for “Write once, run anywhere,” which means it can easily achieve cross-platform capability. Second, it has garbage collection (GC) which allows Java’s garbage collector to handle memory allocation and deallocation, relieving programmers from the responsibility.

In our day-to-day work, we come across JRE (Java Runtime Environment) or JDK (Java Development Kit). JRE includes JVM (Java Virtual Machine), Java class libraries, and other modules. JDK, on the other hand, can be seen as a superset of JRE, providing additional tools such as compilers, various diagnostic tools, etc.

As for the statement “Java is interpreted,” it is not entirely accurate. The Java source code we develop is first compiled into bytecode using Javac. Then, at runtime, the Java Virtual Machine (JVM)’s internal interpreter converts the bytecode into final machine code. However, popular JVMs, such as the Hotspot JVM provided by Oracle JDK, include a Just-In-Time (JIT) compiler. The JIT compiler can dynamically compile hot code into machine code at runtime. In such cases, part of the hot code is considered “compiled execution,” rather than interpreted execution.

Analysis of the Examination Point #

In fact, this question is quite broad. The topic itself is very open-ended and often tests multiple aspects, such as whether your understanding of basic knowledge is clear, and whether you have a grasp of the main modules and operating principles of the Java platform. Many interviewees will struggle with this kind of question and, when feeling a bit nervous, won’t know where to start, resulting in a very concise answer.

For these kinds of broad questions, you need to try your best to demonstrate deep and systematic thinking, as well as a comprehensive understanding of Java knowledge, and make sure to avoid leaving the interviewer with the impression that you only know the surface level of things. After all, understanding the basic components and mechanisms is the foundation for many things in daily work, such as problem diagnosis or performance tuning, and I believe no hiring party would dislike an interviewee who is “passionate about learning and thinking”.

Even if you feel that your answer is not very complete, don’t worry. Personally, I think it is normal to give somewhat one-sided answers to this kind of broad question. Most experienced interviewers will not easily draw conclusions about an interviewee based on a single question. They usually try to guide the interviewee and allow them to showcase their true level. These kinds of questions are just warm-up exercises, and interviewers often use them to expand on related questions based on your answers.

Knowledge Expansion #

Returning to the main topic, we can briefly discuss various aspects of understanding the Java platform, such as Java language features, including generics, lambdas, and other language features, as well as basic libraries like collections, IO/NIO, networking, concurrency, and security. It would be helpful to systematically summarize the libraries that we frequently use in our daily work to aid in on-the-spot performance during interviews.

Alternatively, we can talk about some basic concepts and mechanisms of the JVM, such as Java’s class loading mechanism, commonly used JDK versions (e.g., JDK 8) embedded with Class-Loaders like Bootstrap, Application, and Extension Class-Loader, and the approximate class loading process: loading, verification, linkage, initialization (for reference, I recommend “Understanding the Java Virtual Machine” by Zhou Zhiming, an excellent introductory book on JVM). There is also the topic of custom Class-Loaders. Additionally, we can discuss the basic principles of garbage collection, the most commonly used garbage collectors such as SerialGC, Parallel GC, CMS, and G1, and have a general understanding of which workload each one is best suited for. These are all areas that can be expanded upon, and I will provide a more in-depth introduction in future articles.

Of course, we should also mention the tools included in the JDK or other tools within the Java domain, such as compilers, runtime environments, security tools, diagnostic and monitoring tools, etc. These basic tools are essential for ensuring work efficiency, and they are equally helpful when working on other language platforms. Many concepts can be applied across different platforms.

The following diagram is a relatively broad blueprint that I have summarized for your reference.

We won’t expand further on these topics and will now return to the question about interpreted execution and compiled execution. Some interviewers like to thoroughly investigate specific questions because it is an effective way to assess the level of knowledge a candidate possesses. I will explore this topic a bit more in-depth.

As we all know, Java is typically divided into compilation and runtime. The concepts of compilation in Java and C/C++ are different. In Java, the compilation performed by Javac generates bytecode in the “.class” files, which is not directly executable machine code. Java uses bytecode and the Java Virtual Machine (JVM) as a cross-platform abstraction to shield the details of the operating system and hardware, forming the basis for “write once, run anywhere.”

At runtime, the JVM loads bytecode through class loaders and executes it through interpretation or compilation. As I mentioned earlier, in mainstream Java versions such as JDK 8, interpretation and compilation are mixed in what is known as the mixed mode (-Xmixed). Typically, JVMs running in server mode make thousands of calls to collect enough information for efficient compilation, while the threshold for client mode is 1500 calls. The Oracle Hotspot JVM includes two different JIT compilers: C1, which corresponds to the client mode mentioned earlier and is suitable for applications sensitive to startup speed, such as regular Java desktop applications, and C2, which corresponds to server mode and is optimized for long-running server-side applications. The default is to use tiered compilation. I won’t delve into more JIT details here, as it is not necessary to dive in all at once. I will cover tiered compilation in future content.

When the Java Virtual Machine is started, different parameters can be specified to select different execution modes. For example, using “-Xint” tells the JVM to only perform interpretation without code compilation, abandoning the potential performance benefits of JIT. After all, the interpreter reads and executes code line by line. On the other hand, there is the “-Xcomp” parameter, which tells the JVM to disable interpretation and perform compilation at the maximum optimization level. You might think that this mode is the most efficient, but it’s not that straightforward. Using “-Xcomp” significantly slows down JVM startup, and some JIT compiler optimization techniques, such as branch prediction, often can’t perform effective optimization without profiling.

In addition to the most common Java usage patterns we encounter in our daily work, there is actually a new compilation method known as Ahead-of-Time Compilation (AOT), which directly compiles bytecode into machine code. This avoids the overhead of JIT warm-up, and Oracle JDK 9 introduced an experimental AOT feature and added a new “jaotc” tool. You can use the following commands to compile a specific class or module into an AOT library:

jaotc --output libHelloWorld.so HelloWorld.class
jaotc --output libjava.base.so --module java.base

Then, you can specify it at startup:

java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorld

Furthermore, Oracle JDK supports the collaborative use of tiered compilation and AOT. These two approaches are not mutually exclusive. If you are interested, you can refer to the relevant documentation at http://openjdk.java.net/jeps/295. AOT is not limited to this one method; there have long been third-party tools (such as GCJ, Excelsior JET) that provide similar functionalities.

In addition, the JVM, as a powerful platform, can run not only Java but bytecode that is compliant. Java itself facilitates this, and we can see numerous JVM languages active in different scenarios, such as Clojure, Scala, Groovy, JRuby, Jython, etc.

Today, I briefly introduced some Java platform-related topics with the aim of constructing an overall impression, including Java language features, core libraries and commonly used third-party libraries, basic principles of the Java Virtual Machine and related tools. I hope it is helpful to you.

Practice #

Do you have a clear understanding of the topic we discussed today? It’s better to put knowledge into practice. Please write in the comments section about your understanding of the Java platform. I will select well-thought-out comments and give you a study encouragement reward. Welcome to join me in the discussion.

Are your friends also preparing for interviews? You can “invite your friends to read” and share today’s topic with them. Perhaps you can help them too.