Java基础

JAVA基础

1.jvm什么时候会出现栈内存溢出

->首先要理解栈里面存放的什么(栈帧),存放的是每个方法运行时候都会创建一个栈帧,栈帧里面存的是的
    局部变量表
    操作数栈
    动态链接(多态)
    返回地址
只有到栈里面的栈帧占用空间过大就会导致内存溢出,情景:方法的递归调用

2.如果让你写一段栈溢出代码你会怎么写,一个栈大概有多大,为什么?每个线程都会有这样的一个栈么?

        public class Demo{

            public static void foreach(){
                int age = 10;
                foreach();
            }

            public static void main(String[] args){
                foreach();
            }
        }
一个栈通常只有几百K,-Xss可以分配栈的内存大小,栈不需要太大内存,因为栈的数据结构决定的,每个方法执行完后,都会出栈,不再占据内存
每个线程都会有一个栈的,虚拟机栈和本地方法栈都是线程私有的,而堆,程序计数器都是线程共享的

3.JVM一次完整的GC是怎么样的,怎么样提升至老年代

首先要了解的是JVM里面运行时内存区域-》堆空间-新生代,老年代,和永久代(jdk8后改为了元空间)
新生代又分为伊甸园区,survivor0和survivor1区(in区和out区)
大部分的对象创建都是出生的伊甸园区,当Eden区触发minorGC时,如果对象没有被回收就会存在在survivor0区,如果存放不下就会被直接提升至老年代内存中
一般minorGC触发15次左右就会被survivor0或1区的时候,就会提升至老年代
如果老年代存放不下,就会触发了majorGC,回收老年代的空闲对象,
当老年代和新生代内存不足时,就会出现FullGC,然后STW

4.介绍GC的回收机制和分代回收策略(分代回收见3)

GC的回收机制:
以应用程序root为顶点,遍历应用程序在heap中分配的所有对象,通过识别对象是否已经被root或者其他对象引用,然后进行回收。

5.java中几种引用关系。它们的区别是什么。

1.强引用 -触发gc也不会被回收
2.软引用 -内存不足的时候会被回收
3.弱引用 -触发gc就回收
4.虚引用 -用来检测垃圾回收触发动作的,没啥时候应用场景

6.GC算法有哪些?它们的特点是什么

引用计数法:无法解决循环引用的问题
          回收算法:1.标记-清除算法(先标记后清除,需要遍历两次,内存空间不连续,会有内存碎片)
                  2.复制算法(两块内存,重新拷贝,占用内存)
                  3.标记-压缩算法(效率低)
检测回收:1.引用计数法 2.可达性算法

7.如何判断一个对象是否被回收,有哪些GC算法,实际上虚拟机使用的最多的是什么GC算法

1、可达性算法
2、引用计数法-通过判断对象的引用链是否可达来决定对象是否可以被回收

用到的最多-分代回收算法

8.jvm的内存结构

      ClassLoader
.class ------------------>加载到内存中

运行时数据区
-------------------------------------------
|堆  方法区   本地方法栈   虚拟机栈   程序计数器 |
-------------------------------------------
||               ||
执行引擎<-------本地接口<-------本地库

-类的生命周期

1.加载
2.链接(验证-准备-解析)
3.初始化
4.使用
5.卸载

9.jvm dvm art的区别

dvm(dalvik)和art都不是jvm的一种,并没有遵循jvm规范

dvm和jvm的区别
    1.基于的架构不同,jvm基于栈,dvm是基于寄存器的
    2.执行的字节码不同,jvm是加载.class文件,dvm加载的是.dex文件
    3.dvm运行在有限的内存中同时运行多个进程

ART(android run time) 用来替换dalvik虚拟机

ART和dalvik的区别:
    1.ART对垃圾回收机制进行了改进
    2.ART支持64位并兼容32位cpu,dalvik只支持32位cpu
    3.ART运行时的堆空间划分和dalvik不一样(垃圾收集的方式和策略不一样,Android 8后,采用的是并发压缩算法)
        DVM使用的是标记-清除算法
        ART采用了多种垃圾算法 - CMS 并发压缩算法 -分代收集思想的垃圾算法

10.描述GC机制。class会不会回收,用不到的class怎么回收
--不会

11.StackOverflow和OOM的区别

StackOverflows是栈溢出-只存在于栈中
OOM是内存溢出-堆空间,栈和方法区都有可能出现内存溢出的情况

12.请描述new一个对象的流程

1.判断该对象是否已经被ClassLoader加载过(经历装载,链接,初始化等过程)
2.对象内存的分配-指针碰撞,空闲列表
3.处理并发安全的问题-CAS
4.初始化分配到的内存
5.设置对象的对象头
6.调用对象的init方法进行初始化

13.Java对象会不会分配到栈上

有可能的,有一个叫栈上分配 --->将线程私有的对象打散分配在栈上
    //user的作用域超出了函数setUser的范围,是逃逸对象
    //当函数结束调用时,不会自行销毁user
    private User user;
    public void setUser(){
        user = new User();
        user.setId(1);
        user.setName("blueStarWei");
    }

    //u只在函数内部生效,不是逃逸对象  重点重点-栈上分配
    //当函数调用结束,会自行销毁对象u
    public void createUser(){
        User u = new User();
        u.setId(2);
        u.setName("JVM");
    }

14.String,StringBuilder,StringBuffer的区别

String被final修饰,不可修改,使用常量存放在常量池里,new的话存放在堆
StringBuilder,线程不安全,效率高
StringBuffer,线程安全,效率低

15.String在内存中如何创建的

对于字符串:其对象的引用都是存储在栈中的,
如果是【编译期已经创建好(直接用双引号定义的)的就存储在常量池中】,
如果是【运行期(new出来的)才能确定的就存储在堆中】。对于equals相等的字符串,在常量池中永远只有一份,在堆中有多份。

16.String为什么设计成不可修改的

线程安全,实现常量池

17.final,finally,finalize的区别

final。修饰符,被修饰的对象不能被继承,被修饰的方法不能被重写,被修饰的变量不能在被修改
finally。适用于try-catch-finally,try-resource-finally,确保这段语句会被执行(特殊情况下不会执行,如System.exit(0))
finalize。对象被回收的时候释放一些资源,需要实现finalize

18.抽象类和接口的区别

抽象类只能单继承,接口可以多实现
抽象类有构造方法,接口没有
抽象类能实现方法,接口不行
接口声明的变量会自动被final修饰,不允许修改
抽象类可以实现接口方法,可以不重写接口方法

19.重载和重写的区别

重载是指相同的方法名,拥有不同的方法参数
重写是指子类继承父类的方法,并重新定义方法的实现

20.什么是值传递和引用传递,JAVA是值传递还是引用传递

按值传递是传递的值的拷贝,按引用传递其实传递的是引用的地址值
只有基本类型和按照下面这种定义方式的String是按值传递,其它的都是按引用传递。

21.异常的分类

Throwable
 -Exception
 -Error

22.equals 和 hashcode 的关系?

如果对象相同时,那么hashcode一定相等
如果两个hashcode相同,那么这两个对象也不一定相同

23.什么是三次握手

三次握手(主要是为了验证各个端的正常使用)
	第一次 客户端发送seq 确定了 客户端的 发送能力 和服务端的接收能力
	第二次 服务端返回 seq 和 ack 客户端确认了自己的发送能力和接收能力
	第三次 客户端发送 ack 服务端确定了自己的发送能力
	由此进行数据传输
posted @ 2021-09-04 17:10  lemon亮  阅读(31)  评论(0)    收藏  举报