JVM,我就不信学不会你了

JVM 对 Java 有多重要,对程序员面试有多重要,这些不用多说。

如果你还没意识到学 JVM 的必要性,或者不知道怎么学 JVM,那么看完这篇文章,你就能知道答案了。

曾经的我很不屑于学 JVM,但是后来发现不学不行。这就像和媳妇吵架之后我不想道歉一样,不道歉那是不可能的,道歉是早晚的事儿,逃不掉。

后来我明白了:

认怂越晚,结局越惨。

但是我学的时候才知道:JVM,你太过分了,太难学了!

我的学习过程可以说非常坎坷,不过经历坎坷之后,我倒是发现学 JVM 的门道很多。

以我的经验加上和同行们的交流,我认为学 JVM 最好的方法是:

在程序员不同的水平段,做精准的学习。

所谓的精准学习,就是学习对自己工作有巨大帮助的知识点。以工作内容带动学习,等到积累多了,再一举攻克所有 JVM 知识点,最终熟练掌握 JVM 底层原理。

下面我来说说初级、高级、资深程序员,如何循序渐进、分步学习。

初级程序员怎么学

对刚入行的新手程序员,工作一般是修复简单 bug、开发简单功能。如何编码少出 bug,是这个阶段的核心问题。

对于这个核心问题,JVM 原理必须深入掌握两个知识点。

1. 类的初始化

类的初始化,要了解的非常深入才可以。否则,一不留神就会往项目里引入一些有关初始化的 bug。

比如看看下面这段代码:

public class ParentClass { private int parentX; public ParentClass() { setX(100); } public void setX(int x) { parentX = x; } } public class ChildClass extends ParentClass{ private int childX = 1; public ChildClass() {} @Override public void setX(int x) { super.setX(x); childX = x; System.out.println("ChildX 被赋值为 " + x); } public void printX() { System.out.println("ChildX = " + childX); } } public class TryInitMain { public static void main(String[] args) { ChildClass cc = new ChildClass(); cc.printX(); } }

有兴趣可以运行看看结果,一旦把这种代码放到了生产环境里,排查非常困难。

2. Java 内存结构和对象分配

第二个知识点,就是 Java 内存结构和对象分配的基础知识,尤其是 JVM 内存中堆的布局和对象分配的关系。

比如,堆内存的布局

JVM,我就不信学不会你了

当然,Java7 后,新布局变了

JVM,我就不信学不会你了

知道布局了,就得知道java对象分配的基本原则:

对象优先在Eden区分配

对象太大直接会分配到老年代

只有知道这些知识,才不会经常写下底下这种 bug:

// 将全部行数读取的内存中 List<String> lines = FileUtils.readLines(new File("temp/test.txt"), Charset.defaultCharset()); for (String line : lines) { // pass }

上面这段代码,一旦读取到了大文件,很可能把生产环境搞崩。

所以,把上述两个知识点深入理解了,对新手提升自己的代码质量非常非常有用。只有代码质量上去了,你才能得到更好的发展。

对于这两个知识点,我认为通过网络的文章去学习最好。如果直接看书,有两个最大的缺点:

知识积累不足导致学不懂

书中冗余知识点太多,互相交杂,精力耗费过大,性价比不高

故这里学习推荐根据知识点去搜文章读,而不是找原理性的书籍看。

高级程序员怎么学

对处于这个阶段的朋友,他们已经可以熟练编写健壮的代码了,经常会独立开发出一个大的功能模块,有的可能还能独立开发出一个完整的小型项目。

这时候,他们可能会面临两种情况:

1. 需要写一些工具类给全团队使用

在这种情况下,你很可能就需要 Java 中的语法糖,因为语法糖能让你写出非常灵活简单的代码。这包括泛型,自动拆装箱,可变参数还有遍历循环。

但是,使用这些语法糖的时候,如果你不熟悉他们在 JVM 中的实现原理,就非常容易栽个大跟头,

比如:

public class GenericPitfall { public static void main(String[] args) { List list = new ArrayList(); list.add("123"); List<Integer> list2 = list; System.out.println(list2.get(0).intValue()); } }

2. 编写性能优越的代码

什么时候需要性能优越的代码?最常见的就是把以前性能不好的同步实现,转化成异步实现。

而这种要求,就需要开发对 Java 的多线程开发非常熟悉,并且一定要深入理解多线程在 JVM 中的原理实现。

不然,可以看看下面这段代码:

class IncompletedSynchronization { int x; public int getX() { return x; } public synchronized void setX(int x) { this.x = x; } }

再看看这段:

Object lock = new Object(); synchronized (lock) { lock = new Object(); }

如果把上面这些代码上了生产环境,熬通宵排查问题的命运就注定了……

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgwydw.html