一周面试错题整理(三)

一周面试错题整理(三),第1张

volatile与synchronized的区别:

volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中读取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住.

volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.

volatile仅能实现变量的修改可见性,但不具备原子特性,而synchronized则可以保证变量的修改可见性和原子性.

volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.

volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化.

Java内存结构包含以下部分:

  • 栈区:由编译器自动分配释放,具体方法执行结束后,系统自动释放JVM内存资源。其作用有保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用。也可以用来保存加载方法时的帧。
  • 堆区:一般由程序员分配释放,JVM不定时查看这个对象,如果没有引用指向这个对象就回收。其作用为用来存放动态产生的数据,包括new出来的实例,字符数组等。同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法。
  • 数据区:用来存放static定义的静态成员。
  • 常量池:JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中。

1、运用下列哪个命令能够获取JVM的内存映像(B)

A、jinfo

B、jmap

C、jhat

D、jstat

分析:

  • jps:查看本机java进程信息。
  • jstack:打印线程的栈信息,制作线程dump文件。
  • jinfo:实时查看Java虚拟机各种配置参数和系统属性的命令行工具
  • jmap:打印内存映射,制作堆dump文件
  • jstat:性能监控工具
  • jhat:内存分析工具
  • jconsole:简易的可视化控制台
  • jvisualvm:功能强大的控制台

2、下面代码的执行结果是 :(A)

A、true

B、false

C、TRUE

D、FALSE

分析:

单例模式: 第一步,不让外部调用创建对象,所以把构造器私有化,用private修饰。 第二步,通过本类提供一个方法,供外部调用获取实例。由于没有对象调用,所以此方法为类方法,用static修饰。 第三步,通过方法返回实例对象,由于类方法(静态方法)只能调用静态方法,所以存放该实例的变量改为类变量,用static修饰。 最后,类变量,类方法是在类加载时初始化的,只加载一次。所以由于外部不能创建对象,而且本来实例只在类加载时创建一次

3、对于以下代码段,4个输出语句中输出true的个数是(  C  )。

A、1

B、2

C、3

D、 4

分析:

instanceof是判断前者是否可以类型可以转化为后者,可以转化即为true,分为向上转型和向下转型B D都是A的子类向下转型

4、以下哪个事件会导致线程销毁?(D)

A、调用方法sleep()

B、调用方法wait()

C、start()方法的执行结束

D、run()方法的执行结束

分析:

5、下面有关maven和ant的描述,描述错误的是?(C)

A、Ant 没有正式的约定如一个一般项目的目录结构,你必须明确的告诉 Ant 哪里去找源代码

B、Maven 拥有约定,因为你遵循了约定,它已经知道你的源代码在哪里

C、maven和ant都有“生命周期”的概念,当你输入一个命令后,maven或者ant会执行一系列的有序的步骤,直到到达你指定的生命周期

D、 Ant构建文件默认命名为build.xml,Maven默认构建文件为pom.xml

分析:

Ant和Maven都是基于Java的构建(build)工具。理论上来说,有些类似于(Unix)C中的make ,但没有make的缺陷。Ant是软件构建工具,Maven的定位是软件项目管理和理解工具。
Ant特点

没有一个约定的目录结构

必须明确让ant做什么,什么时候做,然后编译,打包

没有生命周期,必须定义目标及其实现的任务序列

没有集成依赖管理
Maven特点
拥有约定,知道你的代码在哪里,放到哪里去

拥有一个生命周期,例如执行 mvn install 就可以自动执行编译,测试,打包等构建过程

只需要定义一个pom.xml,然后把源码放到默认的目录,Maven帮你处理其他事情

拥有依赖管理,仓库管理

6、从以下四个选项选出不同的一个。(A)

A、LVS

B、Nginx

C、Lighttpd

D、Apache

分析:

其他三个都是web服务器LVS是 Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统

  • LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。
  • Nginx ("engine x") 是一个高性能的 HTTP 和 反向*** 服务器,也是一个 IMAP/POP3/SMTP ***服务器。
  • Lighttpd 是一个德国人领导的开源Web服务器软件,其根本的目的是提供一个专门针对高性能网站,安全、快速、兼容性好并且灵活的web server环境。具有非常低的内存开销、cpu占用率低、效能好以及丰富的模块等特点。
  • Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。

7、关于ThreadLocal类 以下说法正确的是(DE)

A、ThreadLocal继承自Thread

B、ThreadLocal实现了Runnable接口

C、ThreadLocal重要作用在于多线程间的数据共享

D、ThreadLocal是采用哈希表的方式来为每个线程都提供一个变量的副本

E、ThreadLocal保证各个线程间数据安全,每个线程的数据不会被另外线程访问和破坏

分析:

  • ThreadLocal的类声明:public class ThreadLocal     可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。
  • ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,C选项错。由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问,变量被彻底封闭在每个访问的线程中。所以E对。
  • ThreadLocal中定义了一个哈希表用于为每个线程都提供一个变量的副本:

 static class ThreadLocalMap {

        static class Entry extends WeakReference {

            /** The value associated with this ThreadLocal. */

            Object value;

            Entry(ThreadLocal k, Object v) {

                super(k);

                value = v;

            }

        }

        /**

         * The table, resized as necessary.

         * table.length MUST always be a power of two.

         */

        private Entry[] table;

}

所以D对。

8、对 Map 的用法,正确的有:(CD)

A、new java.util.Map().put("key" , "value") ;

B、new java.util.SortedMap().put("key" , "value") ;

C、new java.util.HashMap().put( null , null ) ;

D、new java.util.TreeMap().put( 0 , null ) ;

分析:

选C、D。考察的是Map接口实现类的创建对象以及对象类型包含的方法。

A选项Map属于接口类型,不可以new的方式创建对象。所以A错误。

B选项SortedMap属于接口类型,不可以new的方式创建对象。所以B错误。

C选项HashMap基于哈希表实现Map接口的类,并允许null的值和null键。

D选项TreeMap通过红黑树实现Map接口的类,key不可以为null,会报NullPointerException异常,value可以为null。

9、String s = new String("xyz");创建了几个StringObject?(A)

A、两个或一个都有可能

B、两个

C、一个

D、三个

分析:

 用new关键字创建字符串对象时,JVM会先检查字符串常量池中时候有存在的对应字符串,如果已经存在,则不会在字符串常量池中创建,如果没有存在,那么就会在字符串常量池中创建一个字符串对象,然后还会去堆内存中创建一份字符串对象,把常量池中的对象内容拷贝到内存中的字符串对象,然后返回堆内存中的字符串对象内存地址。若常量池中存在"xyz"那么只在堆内存创建对象。否则还要在常量池中创建一次对象。

10、如下代码的输出结果是什么?(D)

A、0

B、1

C、2

D、编译失败

分析:

静态变量只能在类主体中定义,不能在方法中定义

11、以下 b 的值是: byte b = (byte)129(B)

A、-126

B、-127

C、-128

D、-129

分析:

因为byte是有符号单字节整形,所以存储数字范围是[-128·127]
而127[01111111]+1==128[10000000]。
为什么呢?
因为科学家定义数字的时候是一个环,最大的数字后面就是最小,这样才可以把[0·255]分配给[-128·127]。
底层就是补码的概念。

12、观察下列代码,分析结果(A)

A、false;false; true;

B、false;true; true;

C、false;false; false;

D、true;false; true;

分析:

Java内存结构包含以下部分:

  • 栈区:由编译器自动分配释放,具体方法执行结束后,系统自动释放JVM内存资源。其作用有保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用。也可以用来保存加载方法时的帧。
  • 堆区:一般由程序员分配释放,JVM不定时查看这个对象,如果没有引用指向这个对象就回收。其作用为用来存放动态产生的数据,包括new出来的实例,字符数组等。同一个类的对象拥有各自的成员变量,存储在各自的堆中,但是他们共享该类的方法。
  • 数据区:用来存放static定义的静态成员。
  • 常量池:JVM为每个已加载的类型维护一个常量池,常量池就是这个类型用到的常量的一个有序集合。包括直接常量(基本类型,String)和对其他类型、方法、字段的符号引用。池中的数据和数组一样通过索引访问。由于常量池包含了一个类型所有的对其他类型、方法、字段的符号引用,所以常量池在Java的动态链接中起了核心作用。常量池存在于堆中。

s1,s2都是保存在字符串常量池中的对象;s3是新创建的对象,在堆中;s4,s5指向的也是字符串常量池中的对象;

所以有s3!=s4,s3!=s5,s4=="codercoder"。即为false;false;true。

13、以下哪些内存区域属于JVM规范?(ADE)

A、方法区

B、实例变量

C、静态变量

D、程序计数器

E、虚拟机栈

分析:

JVM内存区:程序计数器、虚拟机栈、本地方法栈、堆、方法区(包括常量池)。

不属于JVM内存区:直接内存(Direct Memory),用户I/O *** 作

jvm规范如图所示

14、 关于Java内存区域下列说法不正确的有哪些(BC)

A、程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器,每个线程都需要一个独立的程序计数器.

B、Java虚拟机栈描述的是java方法执行的内存模型,每个方法被执行的时候都会创建一个栈帧,用于存储局部变量表、类信息、动态链接等信息

C、Java堆是java虚拟机所管理的内存中最大的一块,每个线程都拥有一块内存区域,所有的对象实例以及数组都在这里分配内存。

D、方法区是各个线程共享的内存区域,它用于存储已经被虚拟机加载的常量、即时编译器编译后的代码、静态变量等数据。

分析:

A.程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器(偏移地址),Java编译过程中产生的字节码有点类似编译原理的指令,程序计数器的内存空间存储的是当前执行的字节码的偏移地址,每一个线程都有一个独立的程序计数器(程序计数器的内存空间是线程私有的),因为当执行语句时,改变的是程序计数器的内存空间,因此它不会发生内存溢出 ,并且程序计数器是jvm虚拟机规范中唯一一个没有规定 OutOfMemoryError 异常 的区域;

B.java虚拟机栈:线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表、 *** 作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。  没有类信息,类信息是在方法区中

C.java堆:对于绝大多数应用来说,这块区域是 JVM 所管理的内存中最大的一块。线程共享,主要是存放对象实例和数组

D.方法区:属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

15、有如下一段代码,请选择其运行结果(C)

A、true true

B、false false

C、true false

D、false true

分析:

栈内存中存放Java中的变量、基本类型的值以及指向对象的引用,堆内存中存放new出来的对象本身。栈内存是数据共享的,而堆内存不是数据共享的。例如如下的代码:

     int  i=1;

    String s =  new  String( "Hello World" );

变量i和s以及1存放在栈内存,而s指向的对象”Hello World”存放于堆内存。

 MESSAGE 成员变量及其指向的字符串常量肯定都是在栈内存里的,变量 a 运算完也是指向一个字符串“ taobao ”。编译器的优化,hotspot中 编译时"tao"+"bao"将直接变成"taobao",b+c则不会优化,因为不知道在之前的步骤中bc会不会发生改变,而针对b+c则是用语法糖,新建一个StringBuilder来处理。而栈内存是数据共享的,所以MESSAGE和"tao"+"bao"指向栈内同一个值,它们是相等的,而b+c会指向堆内存中的一个对象,它和MESSAGE不相等。

16、下列哪个说法是正确的(D)

A、ConcurrentHashMap使用synchronized关键字保证线程安全

B、HashMap实现了Collction接口

C、Array.asList方法返回java.util.ArrayList对象

D、SimpleDateFormat是线程不安全的

分析:

A选项中,ConcurrentHashMap 使用segment来分段和管理锁,segment继承自ReentrantLock,因此ConcurrentHashMap使用ReentrantLock来保证线程安全。

B、HashMap定义如下:

public class HashMap
    extends AbstractMap
    implements Map, Cloneable, Serializable

C、应该是Arrays.asList(),其将一个数组转化为一个List对象,这个方***返回一个ArrayList类型的对象, 这个ArrayList类并非java.util.ArrayList类,而是Arrays类的内部类: 

17、给定includel.isp文件代码片段,如下:(B)
  <% pageContext.setAttribute(“User”,”HAHA”);%>
______ // 此处填写代码
  给定include2.jsp文件代码片段如下:
  <%=pageContext.getAttribute(“User”)%>
  要求运行include1.jsp时,浏览器上输出:HAHA 

A、

B、<%@include file=”include2.jsp”%>

C、

D、<% response.sendRedirect(“include2.jsp”); %>

分析:

A选项使用了jsp中动作标签的包含标签,这里是动态包含。原理是包含与被包含的页面单独翻译成不同的java文件,然后运行时合并在一起。因为是存在域中的数据,故刚开始就直接翻译数据还不存在,因此浏览器上不能显示出HAHA。

B选项使用了jsp三大指令中的包含指令,这里是静态包含。原理是直接把包含与被包含页面的内容先合并在一起,然后翻译成一个java源文件,最后编译执行。故可以在浏览器上显示出HAHA。

C和D选项分别使用了跳转和重定向,我们知道jsp中有四个域对象,从小到大分别为:

  • page域:在同一个jsp页面中数据有效
  • request域:在同一个请求中数据有效
  • session域:在用一个会话中数据有效
  • application域:在同一个网站中数据有效

题中使用的是page域对象:pageContext,而C选项应该使用request域对象:HttpServletRequest,而D选项应该至少使用session域对象:HttpSession(如果处于同一会话中)。

18、给出以下代码,请给出结果.(B)

A、null null 42

B、null 42 42

C、0 0 42

D、0 42 42

E、An exception is thrown at runtime

F、Compilation

分析:

19、 

假定str0,...,str4后序代码都是只读引用。
Java 7中,以上述代码为基础,在发生过一次FullGC后,上述代码在Heap空间(不包括PermGen)保留的字符数为(C)

A、5

B、10

C、15

D、 20

解析:

substring实际是new,5字符

str3和4也都是new,每个5字符

分别都会创建新的对象

常量池是PermGen的

因此应该是一共15字符

20、Java的Daemon线程,setDaemon( )设置必须要?(A)

A、在start之前

B、在start之后

C、前后都可以

解析:

setDaemon()方法必须在线程启动之前调用,当线程正在运行时调用会产生异常。

java线程是一个运用很广泛的重点知识,我们很有必要了解java的daemon线程.

首先我们必须清楚的认识到java的线程分为两类: 用户线程和daemon线程

  • 用户线程: 用户线程可以简单的理解为用户定义的线程,当然包括main线程(以前我错误的认为main线程也是一个daemon线程,但是慢慢的发现原来main线程不是,因为如果我再main线程中创建一个用户线程,并且打出日志,我们会发现这样一个问题,main线程运行结束了,但是我们的线程任然在运行).
  • daemon线程: daemon线程是为我们创建的用户线程提供服务的线程,比如说jvm的GC等等,这样的线程有一个非常明显的特征: 当用户线程运行结束的时候,daemon线程将会自动退出.(由此我们可以推出下面关于daemon线程的几条基本特点)

daemon 线程的特点: 

  • 守护线程创建的过程中需要先调用setDaemon方法进行设置,然后再启动线程.否则会报出IllegalThreadStateException异常.(个人在想一个问题,为什么不能动态更改线程为daemon线程?有时间一个补上这个内容,现在给出一个猜测: 是因为jvm判断线程状态的时候,如果当前只存在一个线程Thread1,如果我们把这个线程动态更改为daemon线程,jvm会认为当前已经不存在用户线程而退出,稍后将会给出正确结论,抱歉!如果有哪位大牛看到,希望给出指点,谢谢!)
  • 由于daemon线程的终止条件是当前是否存在用户线程,所以我们不能指派daemon线程来进行一些业务 *** 作,而只能服务用户线程.
  • daemon线程创建的子线程任然是daemon线程.

21、关于 访问权限说法正确 的是 ? ( D )

A、外部类定义前面可以修饰public,protected和private

B、局部内部类前面可以修饰public,protected和private

C、匿名内部类前面可以修饰public,protected和private

D、以上说法都不正确

分析:

  • 外部类前可以修饰:public、default、abstract、final
  • 内部类前可以修饰:public、protected、default、private、abstract、final、static
  • 局部内部类前可以修饰:abstract、final

在Java中,可以将一个类定义在另一个类里面或者一个方法里边,这样的类称为内部类,广泛意义上的内部类一般包括四种:成员内部类,局部内部类,匿名内部类,静态内部类 。

1.成员内部类

(1)该类像是外部类的一个成员,可以无条件的访问外部类的所有成员属性和成员方法(包括private成员和静态成员);

(2)成员内部类拥有与外部类同名的成员变量时,会发生隐藏现象,即默认情况下访问的是成员内部类中的成员。如果要访问外部类中的成员,需要以下形式访问:【外部类.this.成员变量  或  外部类.this.成员方法】;

(3)在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问;

(4)成员内部类是依附外部类而存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象;

(5)内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。如果成员内部类用private修饰,则只能在外部类的内部访问;如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。外部类只能被public和包访问两种权限修饰。

2.局部内部类

(1)局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内;

(2)局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

3.匿名内部类

(1)一般使用匿名内部类的方法来编写事件监听代码;

(2)匿名内部类是不能有访问修饰符和static修饰符的;

(3)匿名内部类是唯一一种没有构造器的类;

(4)匿名内部类用于继承其他类或是实现接口,并不需要增加额外的方法,只是对继承方法的实现或是重写。

4.内部静态类

(1)静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似;

(2)不能使用外部类的非static成员变量或者方法。

22、ServletConfig接口默认是哪里实现的?(B)

A、Servlet

B、GenericServlet

C、HttpServlet

D、用户自定义servlet

分析:

 23、java运行时内存分为“线程共享”和“线程私有”两部分,以下哪些属于“线程共享”部分(BD)

A、程序计算器

B、方法区

C、java虚拟机栈

D、java堆

分析:

JVM 内存可简单分为三个区:

1、堆区(heap):用于存放所有对象,是线程共享的(注:数组也属于对象)

2、栈区(stack):用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:虚拟机栈和本地方法栈)

3、方法区(method):用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也被称为非堆,即 None-Heap)

共享的资源有:

a. 堆  由于堆是在进程空间中开辟出来的,所以它是理所当然地被共享的;因此new出来的都是共享的(16位平台上分全局堆和局部堆,局部堆是独享的)

b. 全局变量 它是与具体某一函数无关的,所以也与特定线程无关;因此也是共享的

c. 静态变量 虽然对于局部变量来说,它在代码中是“放”在某一函数中的,但是其存放位置和全局变量一样,存于堆中开辟的.bss和.data段,是共享的

d. 文件等公用资源  这个是共享的,使用这些公共资源的线程必须同步。Win32 提供了几种同步资源的方式,包括信号、临界区、事件和互斥体。

独享的资源有

a. 栈 栈是独享的

b. 寄存器  这个可能会误解,因为电脑的寄存器是物理的,每个线程去取值难道不一样吗?其实线程里存放的是副本,包括程序计数器PC

24、以下说法哪个是正确的(ABCD)

A、IOException在编译时会被发现

B、NullPointerEception在编译时不会被发现

C、SQLException在编译时会被发现

D、FileNotFoundException在编译时会被发现

分析:

25、下面有关 Java ThreadLocal 说法正确的有?(ABCD)

A、ThreadLocal存放的值是线程封闭,线程间互斥的,主要用于线程内共享一些数据,避免通过参数来传递

B、线程的角度看,每个线程都保持一个对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收

C、在Thread类中有一个Map,用于存储每一个线程的变量的副本。

D、对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式

解析:

ThreadLocal类用于创建一个线程本地变量
在Thread中有一个成员变量ThreadLocals,该变量的类型是ThreadLocalMap,也就是一个Map,它的键是threadLocal,值就是变量的副本,ThreadLocal为每一个使用该变量的线程都提供了一个变量值的副本,每一个线程都可以独立地改变自己的副本,是线程隔离的。通过ThreadLocal的get()方法可以获取该线程变量的本地副本,在get方法之前要先set,否则就要重写initialValue()方法。
ThreadLocal不是用来解决对象共享访问问题的,而主要是提供了保持对象的方法和避免参数传递的方便的对象访问方式。一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。各个线程中访问的是不同的对象。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/797533.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存