JVM面试点记录

一、jvm规范运行时数据区

             

       程序计数器、虚拟机栈、本地方法栈、堆、方法区(非堆/静态存储区)。

       线程私有:程序计数器、虚拟机栈、本地方法栈

       线程共享:堆、方法区

       程序计数器:它就是为多线程准备的,程序计数器是每个线程独有的,所以是线程安全的。记录每个线程的执行情况,保证线程切换后能恢复到正确位置。

       虚拟机栈:经常有人把Java内存划分为堆内存(Heap)和栈内存(Stack)。其中所值的“栈”,就是现在讲的虚拟机栈,或者说是局部变量表

       本地方法栈:与虚拟机栈所发挥的作用类似,是为虚拟机使用的Native方法服务。

       java堆:Java堆是GC的主要场所。细分为:新生代和老年代:新生代又分为Eden区、S0、S1。

       方法区:也叫非堆、或者(静态存储区)用于存储类信息、常量、静态变量等。通俗的讲就是编译后的class文件信息。运行时常量池也是方法区的一部分。

二、对象已死吗

       判断对象是否存活的算法有引用计数法可达性分析

       1、引用计数法

       给对象添加一个引用计数器,每当有一个地方引用它时,计数器值加1;当引用失效,计数器值就减1。

       不能解决对象之间相互循环引用的问题。

       2、可达性分析

       通过一系列的称为“GC Roots”的对象作为起始点(根节点),从起始点开始开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Root没有任何引用链相连,证明此对象不可用。

       根节点:类加载器、常量、static成员。     

三、垃圾收集算法

       介绍几种算法的思想。

       1、标记清除

       先标记可回收对象,然后回收。它的主要不足有两个:一个是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除之后会产生大量不连续的内存碎片。

       2、复制算法

        将内存分成两块,每次只使用其中的一块,当这一块内存用完了,就将还存活的对象复制到另一款上,然后把使用过的内存空间一次清理掉。效率高、空间利用率不高。

       商业虚拟机采用复制算法来回收新生代,新生代中的对象大部分都是朝生夕死,对象存活率较低,Eden:S0:S1=8:1:1

       3、标记整理

        标记可回收对象,将存活对象向一段移动。没有碎片,时间长

       4、分代收集

         Young区(新生代)用复制算法

         Old(老年代)用标记清除或标记整理

四、垃圾收集器

        垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。主要介绍CMS收集器、G1收集器

        1、CMS收集器

         CMS(Concurrent  Mark Sweep)关注停顿时间,从名字(包含“Mark Sweep”)可以看出,CMS收集器是基于“标记--清除”算法实现的。

         2、G1收集器(Garbage First)

         采用分代收集

五、内存分配与回收策略

        对象优先分配在Eden区,没有足够空间时,进行Minor GC,存活的对象进入S0,Eden区被清空。等Eden区又没有足够空间时,进行Minor GC,Eden和S0的存活对象进入S1,Eden和S0被清空。如果对象历经16次Minor GC,仍然存活,直接进入老年代。

        大对象直接进入老年代。

七、虚拟机类加载机制

       1、加载

        根据类的全限定名加载其class文件,转化为Class对象

       2、连接

        ①验证:确保类文件的正确性,比如文件格式。

        ②准备:为所有静态变量分配内存空间,并设置初始值。

        ③解析:将常量池中的符合引用转换为直接引用。

       3、初始化:给类的静态变量赋值(编码阶段给定的值)

八、类加载器

        1、启动类加载器(Bootstrap ClassLoader):

        2、扩展类加载器(Extension ClassLoader):

        3、应用程序类加载器(Application ClassLoader)

        双亲委派模型:

                                                   

九、FullGC

       1、老年代空间不足时

       2、老年代没有足够大的连续空间

       3、System.gc()方法的调用。  

十、常用命令

       1、内存溢出(out of memory)

       jmap导出dump文件,用eclipse memory analyzer进行分析,分析对象的数量和占用内存

       2、处理死循环

      jstack导出文件,top命令找出进程对应的所有线程,找到占用cpu多的线程

       3、处理死锁

       jstack导出文件,找到文件的最后,会看到一个deadlock,死锁的线程。

十 一、何时触发初始化

       1、通过new关键字会导致类的初始化

       2、初始化子类会导致父类的初始化

       3、启动类:执行main函数所在的类会导致该类的初始化

      接下来看一段代码,满足以上三种情况。有三个类:Parent、Children、Test。

public class Parent {
    static {
        System.out.println("static Parent");
    }
    Parent(){
        System.out.println("创建对象parent");
    }
}

Children:

public class Children extends Parent {
    static {
        System.out.println("static Children");
    }
    Children(){
        System.out.println("创建对象children");
    }
}

 Test:

public class Test {
    static {
        System.out.println("static Test");
    }
    public static void main(String[] args) {
        Children children = new Children();
        //Parent parent = new Parent();

    }
}

 最终打印结果如下:

                                                             

      4、访问类的静态变量

      5、访问类的静态方法

      6、对某个类进行反射操作

静态方法代码:

public class StaticMethod {
    static {
        System.out.println("static staticMethod");
    }
    static void method(){
        System.out.println("");
    }
}

 静态变量代码:

public class StaticVar {
    static {
        System.out.println("static staticVar");
    }
    static  String a;
}

  Test类:

public class Test {
    public static void main(String[] args) {
        StaticMethod.method();
        String a = StaticVar.a;
    }
}

最终打印结果如下:

          

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值