面试提问--java基础&JVM虚拟机

1.简述JVM内存模式??

  • 内存私有的:虚拟机栈,本地方法栈,程序计数器
  • 内存共有的:方法区,堆

简述下

  • 栈:栈中存放的是栈帧,是就是方法栈,每个方法从开始到调用完成,是一次完整的入栈出栈的流程
  • 程序计数器:很小的内存区域,用来记录字节码在CPU时间片所执行的位置(执行到哪里了)
  • 方法区:储存被虚拟机啊加载过的一些数据,如:被虚拟机加载的类信息、常量、静态常量、即时编译器编译后的代码等数据
  • 堆:几乎所有对象都在对上创建,new xxx()

2.所有的对象都在对上创建吗??

不是,符合逃逸分析的对象会在栈上分配内存。

3.逃逸分析是什么??

逃逸是指在某个方法之内创建的对象,除了在方法体之内被引用之外,还在方法体之外被其它变量引用到;这样带来的后果是在该方法执行完毕之后,该方法中创建的对象将无法被GC回收,由于其被其它变量引用。正常的方法调用中,方法体中创建的对象将在执行完毕之后,将回收其中创建的对象;故由于无法回收,即成为逃逸。

4.阻塞队列有使用过吗,简述下原理??

阻塞队列,当队列为空,出队操作会阻塞,当队列满了,入队操作会阻塞;先进先出;比喻:一个隧道有一个出口一个入口,隧道最多能容纳10辆车,当隧道内已经有10两车的时候第11辆车就要在外面等待(也就是所谓的插入阻塞);当隧道内没有车的时候,从隧道内取车的这个操作就要等待(阻塞,这里取车比喻的很勉强,哈哈,理解就行);

常用方法(一般都是成对出现)

  • add:非阻塞,当队列满了的时候会抛异常,
  • remove:移除方法,非阻塞,尝试从空的队列取数据是会抛异常
  • off:非阻塞,队列满了 会返回false
  • poll:非阻塞,尝试从空队列取数据则返回null
  • put:阻塞方法,队列满了,则会阻塞
  • take:阻塞方法,当队列为空时,会阻塞

常用的阻塞队列有ArrayBlockingQueue基于数组实现、LinkedBlockingQueue基于链表实现、PriorityBlockingQueue优先级等等

5.GC回收了解吗??如何找到需要回收的对象??

  1. 引用计数法:当这个对象被引用,内部有个变量+1,取消引用-1
    优点:简单 ±1 操作
    缺点:两个对象相互引用,计数不为0

  2. 可达性分析算法:从GC ROOT开始顺着引用链依次寻找,所有节点找完后,其他不在节点上的就是垃圾。

6.常见的GC回收算法有哪几种??适用于什么场景??

  1. 标记清除:扫描的时候给存活的对象打个标记,扫描完后没有被标记的对象就是垃圾;
    缺点:清理后的内存区域不连续,适合老年代
  2. 复制算法:内存换分为两个区域,每次只使用其中一半,一半满了之后将存活的对象复制到另一半内存区域上;
    优点:在另一半上内存区域是连续的,适用于新生代
    缺点:每次只适用一半的内存,浪费内存
  3. 标记整理:在标记清除基础上,增加了移动,使得不连续的内存区域变的连续了;
    优点:内存连续,适用于老年代
    缺点:需要暂停用户线程去做移动操作,性能有一定影响。

7.四大引用类型了解吗??

  1. 强引用:直接引用。例如 private User user; user=new User()
  2. 弱引用:使用WeakReference,只要发生GC就会被回收
  3. 软引用:使用SoftReference,当内存不足的时候才会被回收
  4. 虚引用:任何时候都可能被回收,很少用。

8.什么情况会导致内存栈溢出??

递归调用方法,最常见就是使用动态代理的时候在InvocationHandler的invoke()里又去调用当前对象的方法,这就属于递归去掉invoke()方法;

//申明一个接口
 interface People {
        public void getName();
    }
//定义一个类
 class Man implements People {
        @Override
        public void getName() {
            System.err.println("要");
        }
   }

调用

final People man = new Man();
People people = (People) Proxy.newProxyInstance(man.getClass().getClassLoader(), man.getClass().getInterfaces(),
        new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //注意:在这里如果调用proxy的方法就会栈溢出
                ((People) proxy).getName();
                System.err.println("我");
                Object o = method.invoke(man, args);
                System.err.println("好好学习");
                return o;
            }
        });
people.getName();

运行就会抛出java.lang.StackOverflowError: stack size 8192KB 内存栈溢出

8.final,finally,finalize区别??

  • final:修饰类则该类不能被继承,修饰变量,变量不能被修改;
  • finally:try/catch finally不用多说吧
  • finalize:属于对象Object的方法,在对象回收后可能会被调用;注意是可能,在这里做回收操作不可取;

9.String s=new String("xx);创建了几个对象??

  • 第一个是new String() 的String对象;
  • 第二是“xx”对象,他存在于常量池中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值