测试开发面经(二)

 测试部分
1.测试计划书中要包含的内容

(1)目的与范围  (2)规程     (3)测试方案与方法     (4)测试的准入准出

(5)测试的计划(流程、时间安排、人员安排)(6)环境配置

(7)交附件

2.测试用例要包含的内容

(1)测试项目   (2)编号    (3)测试标题    (4)优先级    (5)预置条件   (6)操作步骤

(7)测试数据      (8)预期结果

3.一个好的bug要包含的内容

(1)编号   (2)严重程度与优先级       (3)简要描述     (4)出现的模块

(5)详细的现象描述,截图、录像等    (6)出现bug的测试环境,产生条件等等

4.如何保证软件质量

(1)需求要吃透   

(2)严格按照测试流程执行,多考虑用户测试场景,使用测试用例设计方法,多评审   

(3)要有良好的测试执行,测试用例通过率达到90%以上,多轮测试,进行探索性测试,使用工具来管理我们的测试过程

5.对测试开发的理解

测试开发首先离不开测试,而软件测试是指,在规定的条件下对程序进行操作,以发现程序错误

 ,衡量程序质量,并对其能否满足设计要求进行评估的过程。

而且,现在不仅仅是通过手工测试来发现bug,也需要编写脚本,测试工具来完成自动化测试。因此,对于测试开发人员来说,他除了保证产品质量外,还需要编写脚本以及开发测试工具。

linux部分
1.查看日志文件中的关键字(字节一面问到了)

(1)使用cat -n filename | grep "关键字"

cat filename | grep -C 10 '关键字' (显示日志里匹配字串那行以及前后10行)

cat filename | grep -B 10 '关键字' (显示匹配字串及前10行)

cat filename | grep -A 10 '关键字' (显示匹配字串及后10行)

(2)使用tail -f 日志文件名 | grep 关键字

tail -f xxx.log             ----实时刷新最新日志
tail -10f xxx.log      --------实时刷新最新的10行日志
tail -10f xxx.log | grep [关键字]     -------查找最新的10行中与关键字匹配的行
tail -10f xxx.log | grep '2021-02-04 11:4[0-9]'    ------查找最新的10行中时间范围在2021-02-04 11:40-2021-02-04 11:49范围中的行
tail -10f xxx.log | grep -A 5 [关键字] ----------查看最新的10行中与关键字匹配的行加上匹配行后的5行

(3)使用vi命令

mysql部分
1.redolog与undolog的区别

(1)redo log:记录的是数据页的物理变化,服务宕机可用来同步数据

(2)undo log记录的是逻辑日志,当事务回滚时,通过逆操作恢复原来的数据

(3)redo log保证了事务的一致性,undo log保证了事务的原子性和一致性

java多线程部分
1.如何保证线程按顺序执行

使用线程中的join()来执行

2.notify()与notifyAll()的区别

notify():随机唤醒一个等待线程

notifyAll():唤醒所有等待线程

3.Java中wait与sleep方法的不同

共同点:

(1)wait,wait(Long)与sleep(long)都是让线程暂时放弃cpu的使用权,进入阻塞状态

不同点:

(1)sleep是Tread中的方法,wait是object中的方法

(2)wait需要synchronized配合使用

(3)wait方法会释放对象锁,允许其他线程获得对象锁,sleep在synchronized中运行不会释放对象锁

4.如何停止一个正在运行的线程

(1)使用退出标志

(2)使用stop方法强行终止,已作废

(3)使用interrupt方法中断线程(打断已经阻塞的线程会报错)

5.synchronized的底层原理

(1)synchronized对象锁采用互斥的方式使得同一时刻只有一个线程能拥有对象锁

(2)底层由monitor实现,monitor是jvm级别的对象(C++),线程获得锁需要使用对象锁关联monitor

(3)在monitor内部有三个属性owner、entrylist、waitset

进阶:

Java的Synchronized有偏向锁,轻量级锁,重量级锁三种形式,分别对应锁只能被一个线程持有、不同线程交替持有,多线程竞争三种情况。

重量级锁:底层使用Monitor实现,里边涉及用户态到内核态的切换,进程的上下文切换,成本较高,性能比较低。

轻量级锁:线程加锁的时间是错开的(也就是没有多次竞争),可以使用轻量级锁来优化,相对重量级锁性能提高很多。每次修改都是CAS操作,保证原子性

偏向锁:一段很长时间内都只能被一个线程使用锁,可以使用偏向锁,在第一次获得锁时,会有一个CAS操作,之后该线程再获取锁,只需要判断mark word是否是自己的线程Id即可,而不是开销比较大的CAS操作         

6.JMM(Java内存模型)

JMM(Java内存模型),定义了共享内存中多线程程序读写操作行为规范,通过这些规则来规范对内存的读写操作来保证指令的正确性

JMM把内存区域分为两块,一块是私有线程的工作区域(工作内存),一块是所有线程的共享区域(主内存)

线程与线程之间相互隔离,线程跟线程交互需要通过主内存

7.对CAS的理解

CAS是基于乐观锁的思想,最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃点亏重试呗

底层调用Unsafe类中的方法实现,都是操作系统提供,其他语言实现

Synchronized是基于悲观锁的思想;最悲观的估计,得当着其他线程来修改共享变量,我上锁你们都想改,我改完了开锁,你们才有机会。

8.谈谈你对volatile的理解

(1)保证线程间的可见性

        对volatile修饰共享变量,能够防止编译器等优化发生,让一个线程对共享变量的修改对另一个线程可见

(2)禁止进行指令重排序

        指令重排:用volatile修饰共享会在读写共享变量时加入不同的屏障,阻止其他读写操作越过屏障,从而达到重排序的效果

9.Synchronized和lock有什么区别

(1)语法层面:

synchronized是关键字,源码在jvm中,用C++实现

lock是接口,源码由jdk提供,用java语言实现

使用synchronized时,退出同步代码块,锁会自动释放,而lock必须使用unlock方法手动释放

(2)功能层面

二者均属于悲观锁,都具备基本的互斥、同步、重入功能

lock提供了许多synchronized不具备的功能,例如公平锁、可打断、可超时、多条件变量

lock有适合不同场景的实现,如:ReentrantLock,ReentrantReadWriteLock(读写锁)

(3)性能层面

在没有竞争时,synchronized做了很多优化,如偏向锁,轻量级锁,性能不赖

在竞争激烈时,Lock的实现通常会提供更好的性能

9.死锁产生的条件

互斥条件,请求与保持条件,循环等待条件,不可剥夺条件

spooling技术,静态分配(一次性分配需要的所有资源),有序的请求资源,要么全拿要么直接抢别人占有的资源

计算机网络部分
1、Get与Post请求区别

(1)安全性:GET数据存储在url中,POST存储在请求体中,post安全度高

(2)对数据长度的限制:GET对数据长度有限制,POST没有

(3)编码方式:GET进能对url编码,POST支持多种编码方式

(4)数据类型限制:GET仅支持ASCII字符,POST对数据类型不作限制(对二进制数据也支持)

JVM部分
JVM组成部分
1、JVM是什么?

Java程序的运行环境 

好处:

(1)一次编写,到处运行

(2)自动内存管理,垃圾回收机制

2、JVM由哪些部分组成,运行流程

(1)Java转换为字节码

(2)把字节码加载到内存

(3)字节码翻译为底层系统指令

(4)C/C++实现

3、你能详细介绍一下堆吗?

(1)堆是线程共享的区域。主要用来存放对象实例,数组等,内存不够则抛出OutOfMemoryError异常。

(2)组成:年轻代和老年代

老年代被划分为三部分,Eden区和两个大小严格相等的Survivor区

老年代主要保存生命周期长的对象,一般是一些老的对象

(3)Jdk1.7和1.8区别

1.7中有一个永久代,存储的是类信息,静态变量,常量,编译后的代码

1.8移除了永久代,把数据 存储在本地内存的元空间中,防止内存溢出

4、什么是虚拟机栈

(1)每个线程运行时需要的内存,称为虚拟机栈,先进后出

(2)每个栈有多个栈帧组成,对应着每次方法调用时所占用的内存

(3)每个线程只能有一个活动栈帧,对应着当前执行的那个方法

5.垃圾回收是否设计栈内存        

不涉及,垃圾回收主要是指堆内存,当栈帧弹栈以后,内存就会释放

6.栈内存分配越大越好吗?

未必,默认栈大小通常为1024kB

栈帧过大会导致线程数变少,例如,机器总内存512m,目前能活动的线程数则为512个,如果把栈内存改为2048k,那么能活动的栈帧就会减半,可以并发的线程数也减少

栈内存越大线程数就会越少,因为物理内存大小是固定的,栈内存越大,可运行线程就越少。比如,一个线程使用栈内存,假设使用1M的内存,物理内存500M,理论上就可以有500个线程同时运行。如果每个线程设置2M,那么只能同时有250个线程运行。所以栈内存分配越大并不是越好,它分配大了通常只是能够进行多次的方法递归调用,而不会增快程序的运行效率,反而会影响线程数目的变少。一般采用默认的就可以,不必在程序启动的时候手动修改。
 

7.方法中局部变量是否线程安全

(1)如果局部变量没有逃离方法的作用范围,他是线性安全的

(2)如果是局部变量引用了对象,并没有逃离方法的作用范围,需要考虑线程安全 

8.栈内存溢出情况

(1)栈帧过多导致内存溢出,典型问题:递归调用

(2)栈帧过大导致栈内存溢出

9.堆栈的区别

(1)栈内存一般用来存储局部变量和方法调用,但是堆内存是用来存储java对象和数组的堆。堆会进行CG垃圾回收,而栈不会

(2)栈内存是线程私有的,堆内存是线程共享的

10.能不能解释一下方法区

(1)方法区是各个线程共享的内存区域

(2)主要存储类的信息,运行时常量池,类加载器等等

(3)虚拟机启动时创建,关闭虚拟机时释放

(4)如果方法区域中的内存无法满足内存空间,会抛出异常

11.介绍一下运行时常量池

常量池:可以看作一张表,虚拟机指令根据这张表找到要执行的类名,方法名,参数类型,字面量等信息

当类被加载时,它的常量池信息就会放入运行时常量池,并把里面的符号地址转换为真实地址

12.你听说过直接内存吗?

(1)直接内存并不属于JVM内存结构,不由JVM进行管理。是虚拟机的系统内存。

(2)在常见的NIO操作时,用于数据缓冲区,分配回收成本较高,但读写性能高,不受JVM内存回收管理

(3)常见的IO数据拷贝,不仅涉及到用户态和内核态的切换,在磁盘-系统缓冲区-java缓冲区之间还存在一层拷贝,这会影响IO操作的性能

(4)直接内存就是系统和java代码都可以访问到的一块缓冲区

JVM类加载器部分
1.什么是类加载器,类加载器有哪些?

(1)JVM只会运行二进制文件,类加载器将Java字节码文件加载到JVM中,从而让java文件可以运行起来

(2)启动类加载器,拓展类加载器,应用类加载器,自定义类加载器

2.什么是双亲委派模型,为什么采用双亲委派机制

        双亲委派机制是加载某一个类时,先委托上一级的加载器进行加载,如果上级加载器也有上级,则会继续向上委托,如果上级加载器没有被加载,则交给子加载器进行加载

采用双亲委派机制的原因

        1)通过双亲委派机制可以避免某一个类被重复加载,保证唯一性

        2)为了安全,保证类库API不会被加载

3.说一下类装载的执行过程

加载:查找和导入class文件

验证:保证加载类的准确性

准备:为类变量分配内存并设置类变量初始值

解析:把类中的符号引用转化为直接引用

初始化:对类的静态变量、静态代码块执行那个初始化操作

使用:JVM开始从入口方法开始执行用户的程序代码

卸载:当用户代码执行完毕后,JVM开始销毁创建的Class对象

CG垃圾回收部分
1.垃圾什么时候可以被回收?定位垃圾的两种办法

(1)没有引用指向  

(2)引用计数法(循环引用会导致其失效 ),可达性分析法 

2.垃圾回收算法有哪些?

(1)标记清除算法

先试用可达性分析算法进行标记,再对这些标记可回收内容进行回收

优点:标记和清除速度更快

缺点:碎片化较为严重,内容不连贯

(2)标记整理算法(常用于老年代)

(3)复制算法(年轻代)

优点:在垃圾对象比较多的情况下,效率较高

        清理后,内存无碎片

缺点:分配两块内存空间,同一时刻,只能使用一半,内存使用率较低

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值