通过一段代码在 JVM 中运行情况来分析:

  1. public class Kafka {
  2. private static ReplicaFetcher fetcher = new ReplicaFetcher();
  3. public static void main(String[] args){
  4. loadReplicasFromDisk();
  5. while(true){
  6. fetchReplicasFromRemote();
  7. Thread.sleep(1000);
  8. }
  9. }
  10. private static void loadReplicasFromDisk(){
  11. ReplicaManager replicaManager = new ReplicaManager();
  12. replicaManager.load();
  13. }
  14. private static void fetchReplicasFromRemote(){
  15. fetcher.fetch();
  16. }
  17. }

image.png

1. 什么是年轻代、老年代、永久代?

  • 年轻代:
    • 像 ReplicaManager 对象,在方法中被创建的对象实例,在方法执行完后,就没有任何变量引用这个对象,很快被垃圾回收掉;
    • 代码中,绝大多数对象都是像这样存活周期极短,都被放在 Java 堆内存的年轻代;
  • 老年代:
    • 像 ReplicaFetcher 对象,被类的静态变量引用的,他开始会放在年轻代,但是随着长期的被引用,它会被转移到老年代;
    • 代码中,少数对象会有很长的生命周期,需要不停的被使用,都被放在 Java 堆内存的老年代;
  • 永久代:
    • 像 Kafka 类,它的类信息会放在方法区,这个方法区就是永久代;
    • 方法区,即所谓的永久代,存放一些类信息的;

2. Java 堆内存为什么要分成年轻代和老年代?

  • 和垃圾回收有关;
  • 年轻代的对象生命周期短,老年代的生命周期长,所以需要将内存堆划分成两个不同区域,各自使用不同的垃圾回收算法;