代码之旅

I love Coding !

多任务处理在现代计算机操作系统中是一个必备功能。计算机的运算能力变得十分强大的同时,运算速度与存储和通信子系统速度的差距太大,大量的时间都花费在磁盘I/O、网络通信和数据库访问上,因此为了避免处理器的大部分时间都花费在等待其它资源,一种行之有效的方法是让计算机同时处理多项任务。

阅读全文 »

HotSpot虚拟机实现GC算法时,必须对算法的执行效率有严格的考量,才能保证虚拟机的高效运行。

阅读全文 »

浮点数是计算机科学中一种对于实数的近似数值表示法,由一个有效数字(尾数)加上幂数来表示,即二进制的科学计数法。IEEE 协会为了规范统一(方便CPU指令制造,各平台兼容等等)出台了 IEEE Standard for Floating-Point Arithmetic(IEEE-754)二进制浮点数算数标准,选用了浮点数作为储存和算数标准。 该标准描述了包括"浮点数的格式"、“一些特殊数值”、“浮点数的运算”、“舍入规则与例外情况” 等等内容。

阅读全文 »

对象的内存分配,主要是在堆上分配(也可能是JIT编译后被拆散成标量类型并间接的栈上分配),对象主要分配在新生代的Eden区上,如果启动了本地线程分配缓冲,将按线程优先分配在TLAB上。少数情况下会直接分配在老年代中。分配的规则并不是百分百固定的,细节取决于当前使用的是哪一种垃圾收集器组合,还有虚拟机中与内存相关的参数设置。

新生代GC(Minor GC)指发生在新生代的垃圾回收动作,Minor GC十分频繁,回收速度较快。
老年代GC(Major/Full GC)指发生在老年代的GC,出现了Major GC,经常会伴随至少一次Minor GC ,但非绝对,Parallel Scavenger 收集器里有直接进行Major GC的策略选择。通常,Major GC 比Minor GC 慢10倍以上。

阅读全文 »

在了解垃圾回收算法前,我们先要了解几个基本概念。

首先是mutator和collector,这两个名词经常在垃圾收集算法中出现,collector指的就是垃圾收集器,而mutator是指除了垃圾收集器之外的部分,比如说我们应用程序本身。mutator的职责一般是NEW(分配内存),READ(从内存中读取内容),WRITE(将内容写入内存),而collector则就是回收不再使用的内存来供mutator进行NEW操作的使用。

第二个基本概念是关于mutator roots(mutator根对象),mutator根对象一般指的是分配在堆内存之外,可以直接被mutator直接访问到的对象,一般是指静态/全局变量以及Thread-Local变量(在Java中,存储在java.lang.ThreadLocal中的变量和分配在栈上的变量,方法内部的临时变量等都属于此类).

第三个基本概念是关于可达对象的定义,从mutator根对象开始进行遍历,可以被访问到的对象都称为是可达对象。这些对象也是mutator(你的应用程序)正在使用的对象。

阅读全文 »

GC的三个问题:

  1. 哪些内存需要回收?
  2. 什么时候回收?
  3. 如何回收?

对于Java内存的各个区域,

  • 程序计数器、虚拟机栈、本地方法栈这3个区域属于线程私有区域,随线程生死。虚拟机栈中的栈帧随着方法的进入和退出执行出栈,入栈操作。每个栈帧分配多少内存基本上在类结构中就可以确定,并且方法结束或线程结束时回收内存。因此这几个区域内不需要考虑回收内存。
  • java堆和方法区是属于线程共享区域。只有在程序运行时才能知道创建了多少对象,内存是动态分配的,因此,我们需要考虑的是这部分内存的动态回收。
阅读全文 »

线程有时也被称为轻量级的进程。进程和线程都提供了一个执行环境,但创建一个新的线程比创建一个新的进程需要的资源要少。 线程是在进程中存在的,每个进程最少有一个线程。线程共享进程的资源,包括内存和打开的文件。这样提高了效率,但潜在的问题就是线程间的通信。

阅读全文 »

开始比较前,先来了解下循环和递归的定义。

  • 循环是一段在程序中只出现一次,但可能会连续执行多次的代码。循环中的代码会执行特定的次数(例如for),或者是执行到特定条件成立时结束循环(例如while),或者是针对某一集合中的所有项目都执行一次。
  • 递归指在函数的定义中使用函数自身的方法,即一个函数不断调用自身的行为。

在一些函数编程语言(例如Haskell和Scheme)中会使用递归或不动点组合子来达到循环的效果。

阅读全文 »

在前面的Java虚拟机-内存布局一文中我们简单介绍了虚拟机栈:

  • java虚拟机栈是线程私有的,他与线程的声明周期同步。虚拟机栈描述的是java方法执行的内存模型。
  • 每个方法执行都会创建一个栈帧,栈帧包含局部变量表、操作数栈、动态连接、方法出口等。

本文将继续详细介绍虚拟机栈。

阅读全文 »

在HotSpot JVM(jvm 8以前)中,永久代中用于存放类和方法的元数据以及常量池,在Java中对应能通过反射获取到的数据,比如Class和Method。每当一个类初次被加载的时候,它的元数据都会放到永久代中。永久代是有大小限制的(启动时设置),因此如果加载的类太多,很有可能导致永久代内存溢出(java.lang.OutOfMemoryError: PermGen)。Java 8为了解决这一问题,彻底将永久代移除出了HotSpot JVM,将其原有的数据迁移至Java Heap或Metaspace(见参考【1】)。

阅读全文 »