• notice
  • Congratulations on the launch of the Sought Tech site

How do I read the JDK source code?

1 Introduction

I have read the source code of some commonly used JDK classes on and off before, and here I want to record some of the experiences and methods in the process.

This article mainly shares my reading tools and reading order.

PS: Since the current mainstream JDK version is still 1.8, the source code reading is mainly 1.8 version, and some places can refer to 1.7 (may be asked in the interview).

2. Tools

If a worker wants to do a good job, he must first sharpen his tools.

Not many tools needed, IDE + Google Translate is enough.

The main purpose of using an IDE is to be able to write some test code for trace debugging. This is still necessary, and it is easier to follow the execution flow of the code to understand its implementation principle.

Open the source code file directly in the IDE. The comments in the source code are usually very detailed. When you encounter something you don't understand, Google translate it. You can also add official documents. In fact, the comments in the source code are the same as the documents. Some places may be more detailed, but the layout of the official documents is more beautiful.

JDK 1.8 official documentation link: https://docs.oracle.com/javase/8/docs/api/

Of course, the order of reading is also very important. The following is my reading order.

3. Reading order

3.1 Overall order

There is a lot of code in the JDK, and it is impossible and unnecessary to read it all, so it must be targeted. Overall, the order is roughly:

  1. Collection Framework Classes
    1. It mainly includes a series of common classes and interfaces composed of Collection, Map, Queue, etc., including ArrayList, LinkedList, HashMap, etc.
    2. This part of the content is used more in daily development, and interviews appear frequently, so you can start here first.
  2. concurrent package
    1. That is, the common classes under the java.util.concurrent (JUC) package, including ReentrantLock, ThreadPoolExecutor, AQS, etc.
    2. This part provides common tool classes for concurrent programming, and is also frequently used in interviews.
  3. Other common classes
    1. For example ThreadLocal, String, StringBuilder, StringBuffer, etc.

The overall overview is as follows:

244cf4fb11c93848802d3bcd91a5acea.png

Specific to a certain class, how to read its source code implementation? Continue below.

3.2 Specific sequence

3.2.1 Classes and Interfaces

How to read the source code of a class? The main steps are roughly:

  1. Read the interface code first. Including interface documentation, definition and documentation of each method.
  2. Then read the main method implementation of the implementation class, there are usually the following two main line entries:
    1. Construction method
    2. Common method

In Java, an interface usually means a "standard", or "protocol". An interface can have multiple implementation classes, and they will all implement each method of the interface according to the standard of the interface. Therefore, after understanding the definition of a method, it will be easier to understand when looking at its implementation.

Let's take the commonly used ArrayList as an example to analyze how to read its source code.

3.2.2 ArrayList source code analysis

First look at the inheritance structure of ArrayList:

c6c4f60d244c1b4dee0a2ea0f36dfba8.png

You can see that it implements many interfaces, three of which are Cloneable, RandomAccess, and Serializable are empty and can be ignored for the time being. Mainly to see the method definitions of Iterable, Collection and List interfaces.

Iterable interface:

f61ee0a1ffe253d665557388ab600e7b.png

Collection interface:

e69f6528c20eda5d86cf884c7ac99560.png

List interface:

58e9cecf34ae3331f4e9fd1712aa1059.png

It seems that there are many methods, but in fact, many of them are what we usually use. Most of them are not difficult to understand, and the methods are also annotated. This part is not difficult.

Next, according to the two main line entries mentioned above, analyze how to read the source code of ArrayList.

  • Constructor

Constructors are often a good entry point when analyzing the source code of a class. For example, the three constructors of ArrayList are as follows:

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray might (incorrectly) not return Object[] (see 6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

There are many member variables in the constructor, such as elementData, EMPTY_ELEMENTDATA, DEFAULTCAPACITY_EMPTY_ELEMENTDATA, etc., continue to follow these variables:

private static final Object[] EMPTY_ELEMENTDATA = {};

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

transient Object[] elementData; // non-private to simplify nested class access

From this we can see what was going on inside it new ArrayList()when .

  • Common method

In addition to the constructor, common methods are also a main entry, such as add, remove, etc.

add method implementation:

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

You can follow the code line by line to see what's going on inside the add method.

The same is true for the routines of other methods, and will not be explained one by one.

Following such a main line, you can have an overall understanding of the implementation principle of ArrayList. After the whole part is figured out, you can also read some less commonly used methods, including all the remaining parts.

PS: Here is just an example of the commonly used ArrayList, and the reading steps of classes under other packages are similar.

3.3 Take notes

Also, taking notes is important.

You can use the mind map to sort out the overall context, and use the note-taking tool to record the implementation principle of the core part of a class.

Of course, it is better if you organize and write your own notes. Many times, you always feel that you know it, but when someone asks you, you are confused. Maybe you still don't understand it properly.

There is a saying that goes well: "Teaching is the best learning". When you can tell a certain knowledge point to a layman in an easy-to-understand manner, then you really understand it.

3.4 Notes

When you first start reading, you may encounter some places that are difficult to understand. You can try to write test code breakpoints to trace and debug, or refer to other people's blogs.

If you encounter a certain point that is really difficult to understand, you can skip it first, and rethink it after a while and you may suddenly become enlightened.

PS:

  1. The above content is purely personal opinion and is for reference only.
  2. In addition, I organized the notes of the previous article into an e-book, and you can get it by replying to the "JDK source code" in the background.


Tags

Technical otaku

Sought technology together

Related Topic

0 Comments

Leave a Reply

+