下面有关JVM内存,说法错误的是?

A.程序计数器是一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的
B.虚拟机栈描述的是Java方法执行的内存模型,用于存储局部变量,操作数栈,动态链接,方法出口等信息,是线程隔离的
C.方法区用于存储JVM加载的类信息、常量、静态变量、以及编译器编译后的代码等数据,是线程隔离的
D.原则上讲,所有的对象都在堆区上分配内存,是线程之间共享的

正确答案:C

解析:大多数的JVM将内存划分为Method Area(Non-Heap)(方法区)、Heap(堆)、Program Counter Register(程序计数器),VM Stack(虚拟机栈,也有
翻译成Java方法栈的),Native Method Stack(本地方法栈),其中方法区和堆是线程共享的。为什么要分为线程共享和线程不共享的呢?
首先我们熟悉一下一般性的Java程序的工作过程:一个Java源程序,会被编译成字节码文件(.class),每一个Java程序都需要运行在自己的JVM上,
然后告知JVM程序的入口,再被JVM通过字节码解释器加载运行.那么程序开始运行之后是如何设计到各内存区域的呢?
概括地说,JVM初始运行时都会分配好方法区和堆,而JVM每遇到一个线程,就为其分配一个程序计数器、虚拟机栈和本地方法栈,当线程终止时,三
者所占用的内存空间也会被释放掉。非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与Java程序运行的生命周期相同,所以,
这也是系统回收垃圾的场所只发生在线程共享的区域(实际上对大部分虚拟机来说只发生在堆上)的原因。
图片说明
方法区域存放了所加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息,当
开发人员在程序中通过Class对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在
一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息

下面有关jdbc statement的说法错误的是?

正确答案: C 你的答案: C (正确)

A.JDBC提供了Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询,PreparedStatement 用于执行参数化查询, 而 CallableStatement则是用于存储过程
B.对于PreparedStatement来说,数据库可以使用已经编译过及定义好的执行计划,由于 PreparedStatement 对象已预编译过,所以其执行速度要快于Statement 对象”
D.PreparedStatement中,“?” 叫做占位符,一个占位符可以有一个或者多个值
PreparedStatement可以阻止常见的SQL注入式攻击
解析:

  1. Statement、PreparedStatement和CallStatement都是接口(interface)
  2. Statemnet继承自Wapper、PreparedStatement继承自Statement、CallStatement继承自PreparedStatement
  3. Statement接口提供了执行语句和获取结果的基本方法
    PreparedStatement接口添加了处理IN参数的方法
    CallStatement接口添加了处理OUT参数的方法
  4. Statement:普通的不带参的查询;支持批量更新、批量删除
    PreparedStatement:可变参数的SQL,编译一次,执行多次,效率高;安全性好,有效防止SQL注入等问题;支持批量更新、批量删除
    CallStatement:支持带参数的SQL操作;支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持
  5. Statement每次执行SQL语句,数据库都要执行SQL语句的编译,最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement
  6. PreparedStatement是预编译的,其优点:
    a. 在执行可变参数的一条SQL时,PreparedStatement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL效率要高。
    b. 安全性好,有效防止SQL注入等问题
    c. 对于多次重复执行的语句,使用PreparedStatement效率会高一些
    d. 代码的可读性和可维护性要更好
  7. PReparedStatement的占位符对应着即将与之对应当值,并且一个占位符只能对应一个值,如果能对应多个就会引起混淆。sql语句是确定的,那么一个占位符必定只能对应一个值

下面有关SPRING的事务传播特性,说法错误的是?

正确答案: B 你的答案: B (正确)

A.PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行
B.PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就抛出异常
C.PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
D.PROPAGATION_NESTED:支持当前事务,新增Savepoint点,与当前事务同步提交或回滚
解析:事务属性的种类:传播行为、隔离级别、只读和事务超时

  1. 传播行为定义了被调用方法的事务边界
    图片说明

  2. 隔离级别:在操作数据时可能带来3个副作用,分别时脏读、不可重复度、幻读 ,为了避免这3种副作用的发生,在标准的SQL语句中定义了4种隔离级别,分别是不可提交读、已提交读、
    可重复读、可序列化。而在spring事务中提供了5中隔离级别来应对在SQL中定义的四种隔离界别,如下:
    图片说明

  3. 只读:
    如果一个事务中所有关于数据库的操作都是只读的,也就是说,这些操作只读数据库中的数据,而并不更新数据,那么应将事务设为只读模式(READ_ONLY_MARKEY),这样更有利于数据库的优化。因为只读的优化措施是事务启动后由数据库实施的,因此,只有将那些具有可能启动新事物的传播行为(PROPAGATION_NESTED、PROPAGATION_REQUIRED、PROPAGATION_REQUIRE_NEW)的方法的事务标记为只读才有意义。
    如果使用Hibernate作为持久化机制,那么将事务标记为只读后,会将Hibernate的flush模式设置为FULSH_NEVER,以告诉Hibernate避免和数据库之间进行不必要的同步,并将所有更新延迟
    到事务结束

  4. 事务超时:如果一个事务长时间运行,这时为了尽量避免浪费系统资源,应为这个事务设置一个有效时间,使其等待数秒后自动回滚。与设置只读属性一样,事务有效属性也需要给那些具
    有可能启动新事物的传播行为的方法的事务标记成只读才有意义。

下面有关servlet service描述错误的是?

正确答案: B 你的答案: A (错误)

A. 不管是post还是get方法提交过来的连接,都会在service中处理
B. doGet/doPost 则是在 javax.servlet.GenericServlet 中实现的
C. service()是在javax.servlet.Servlet接口中定义的
D.service判断请求类型,决定是调用doGet还是doPost方法
解析:doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的

下列有关Servlet的生命周期,说法不正确的是?

正确答案: A 你的答案: D (错误)

A. 在创建自己的Servlet时候,应该在初始化方法init()方法中创建Servlet实例
B. 在Servlet生命周期的服务阶段,执行service()方法,根据用户请求的方法,执行相应的doGet()或是doPost()方法
C. 在销毁阶段,执行destroy()方法后会释放Servlet 占用的资源
D. destroy()方法仅执行一次,即在服务器停止且卸载Servlet时执行该方法
解析:servlet的生命周期分为5个阶段

  1. 加载:容器通过类加载器使用servlet类对应的文件来加载servlet
  2. 创建:通过调用servlet的构造函数来创建一个servlet实例
  3. 初始化:通过调用servlet的init()方法来完成初始化工作,这个方法实在servlet已经被创建,但在向客户端提供服务之前使用
  4. 处理客户请求:servlet创建后就可以处理请求,当有新的客户端请求时,web容器都会创建一个新的线程来处理该请求。接着调用servlet的service()方法来响应客户端请求,service()方法根据请求的method属性来调用doGet()和doPost()方法
  5. 卸载:调用destroy方法让servlet自己释放其占用的资源

下面有关servlet中init,service,destroy方法描述错误的是?

正确答案: D 你的答案: A (错误)

A. init()方法是servlet生命的起点。一旦加载了某个servlet,服务器将立即调用它的init()方法
B.service()方法处理客户机发出的所有请求
C.destroy()方法标志servlet生命周期的结束
D.servlet在多线程下使用了同步机制,因此,在并发编程下servlet是线程安全的
解析:servlet在多线程下其本身并不是线程安全的。
如果在类中定义成员变量,而在service中根据不同的线程对该成员变量进行更改,那么在并发的时候就会引起错误。最好是在方法中,定义局部变量,而不是类变量或者对象的成员变量。
由于方法中的局部变量是在栈中,彼此各自都拥有独立的运行空间而不会互相干扰,因此才做到线程安全。

下面有关struts1和struts2的区别,描述错误的是?

正确答案: B 你的答案: D (错误)

A. Struts1要求Action类继承一个抽象基类。Struts 2 Action类可以实现一个Action接口
B. Struts1 Action对象为每一个请求产生一个实例。Struts2 Action是单例模式并且必须是线程安全的
C. Struts1 Action 依赖于Servlet API,Struts 2 Action不依赖于容器,允许Action脱离容器单独被测试
D. Struts1 整合了JSTL,Struts2可以使用JSTL,但是也支持OGNL
解析:
从action类上分析:

  1. Struts1要求Action继承一个抽象基类。Struts1的普遍问题是使用抽象类编程而不是接口
  2. Struts2Action类可以实现一个Action接口,也可以实现其他接口,使可选和定制的服务称为可能。Struts2提供一个ActionSupport基类去实现常用的接口。Action接口不是必须的,任何由execute标识的POJO对象都可以作为Struts2的Action对象。

从Servlet依赖分析:

  1. Struts1 Action 依赖于Servlet API ,因为当一个Action被调用时HttpServletRequest 和 HttpServletResponse 被传递给execute方法。
  2. Struts2 Action不依赖于容器,允许Action脱离容器单独被测试。如果需要,Struts2 Action仍然可以访问初始的request和response。但是,其他的元素减少或者消除了直接访问HttpServetRequest 和 HttpServletResponse的必要性。

从action线程模式分析:

  1. Struts1 Action是单例模式并且必须是线程安全的,因为仅有Action的一个实例来处理所有请求。单例策略限制了Struts1 Action能作的事,并且要在开发时特别小心。Action资源必须是线程安全的或同步的。
  2. Struts2 Action对象为每一个请求产生一个实例,因此没有线程安全问题。(实际上,servlet容器给每个请求产生许多可丢弃的对象,并且不会导致性能和垃圾回收问题)

看以下代码:

文件名称:forward.jsp

<html>  
     <head><title> 跳转  </title> </head> 
     <body>  
         <jsp:forward page="index.htm"/>     
     </body>
 </html> 

如果运行以上jsp文件,地址栏的内容为

正确答案: A 你的答案: C (错误)

A. http://127.0.0.1:8080/myjsp/forward.jsp
B. http://127.0.0.1:8080/myjsp/index.jsp
C. http://127.0.0.1:8080/myjsp/index.htm
D. http://127.0.0.1:8080/myjsp/forward.htm

解析:
forward,请求转发,服务器获取跳转页面内容传给用户,用户地址栏不变
redirect,请求重定向,是服务器向用户发送转向的地址,redirect后地址栏变成新的地址

下面哪一项不是加载驱动程序的方法?

正确答案: A 你的答案: D (错误)

A. 通过DriverManager.getConnection方法加载
B. 调用方法 Class.forName
C. 通过添加系统的jdbc.drivers属性
D. 通过registerDriver方法注册

解析:加载驱动方法:

  1. Class.forName("com.mysql.jdbc.Driver")
  2. DriverManager.registerDriver(new com.mysql.jdbc.Driver())
  3. System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver")

根据下面的程序代码,哪些选项的值返回true?

图片说明

正确答案: C 你的答案: D (错误)

A. a == b
B. s == a
C. b == c
D. a.equals(s)

解析:这题考的是引用和内存

    publicclassSquare {  
        longwidth;  
        publicSquare(longl) {   
         width = l;  
        }  
        publicstaticvoidmain(String arg[]) { 
        // 声明了3个Square类型的变量 a,b,c   
         Square a, b, c;   
        // 在Heap(堆)中分配了一块新内存,里面包含了自己的成员变量width值为42L,
        // 然后stack(栈)中的a指向这块内存      
         a = newSquare(42L);  
         // 在Heap(堆)中分配了一块新内存,里面包含了自己的成员变量width值为42L,  
         // 然后stack(栈)中的b指向这块内存 
         b = newSquare(42L);    
         // stack(栈)中的c也指向b所指向的内存    
         c = b;      
         // 在stack中分配了一块内存,值为42         
         longs = 42L;           
        } 

    来看4个选项:
    A: a == b
    由图可以看出a和b指向的不是同一个引用,故A错
    B:s == a
    一个Square类型不能与一个long型比较,编译就错误,故B错
    c:b == c
    由图可以看出b和c指向的是同一个引用,故C正确
    d:a equal s
    程序会把s封装成一个Long类型,由于Square没有重写Object的equals方法
      ,所以调用的是Object类的equals方法,源码如下:
     public boolean equals(Object obj) {
         return (this == obj);
         }                      
     其实就是判断两个引用是否相等,故D也错误。

在jdk1.5的环境下,有如下4条语句:

Integer i01 = 59;
inti02 = 59;
Integer i03 =Integer.valueOf(59);
Integer i04 = newInteger(59);

以下输出结果为false的是:

正确答案: C 你的答案: C (正确)

A. System.out.println(i01 == i02);
B. System.out.println(i01 == i03);
C. System.out.println(i03 == i04);
D. System.out.println(i02 == i04);

解析:
Integer i01=59的时候,会调用Integer的valueOf方法

  publicstaticInteger valueOf(inti) {
     assertIntegerCache.high>= 127;    
     if(i >= IntegerCache.low&& i <= IntegerCache.high)
     return IntegerCache.***[i+ (-IntegerCache.low)];
     return new Integer(i); } 

这个方法就是返回一个Integer对象,只是在返回之前,看作了一个判断,判断当前i的值是否在[-128,127]区别,且IntegerCache中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新的对象。在这里,一位内程序初次运行,所以直接创建了一个新的对象。
int i02=59 ,这是一个基本类型,存储在栈中。
Integer i03 =Integer.valueOf(59); 因为IntegerCache中已经存在此对象,所以,直接返回引用。
Integer i04 = new Integer(59);直接创建一个新的对象。
System.out.println(i01== i02);i01是Integer对象,i02是int,这里比较的不是地址,而是值。Integer会自动拆箱成int,然后进行值的比较。所以,为真。
System.out.println(i01== i03);因为i03返回的是i01的引用,所以为真
System.out.println(i03==i04);因为i04是重新创建的对象,所以i03,i04是指向不同的对象,因此比较结果为假
System.out.println(i02== i04);因为i02是基本类型,所以此时i04会自动拆箱,进行值比较,所以,结果为真。
补充:IntegerCache为Integer类的缓存类,默认缓存了-128~127的Integer值,如遇到[-128,127]范围的值需要转换为Integer时会直接从IntegerCache中获取

关于以下程序代码的说明正确的是?

1.   publicclassHasStatic{
2.     privatestaticintx=100;
3.     publicstaticvoidmain(String args[]){
4.          HasStatic hs1=newHasStatic();
5.          hs1.x++;
6.          HasStatic  hs2=newHasStatic();
7.          hs2.x++;
8.          hs1=newHasStatic();
9.          hs1.x++;
10.        HasStatic.x--;
11.        System.out.println("x="+x);
12.     }
13.   }     

正确答案: D 你的答案: A (错误)

A. 程序通过编译,输出结果为:x=103
B. 10行不能通过编译,因为x是私有静态变量
C. 5行不能通过编译,因为引用了私有静态变量
D. 程序通过编译,输出结果为:x=102

解析:static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态的代码块,但是
Java语言中不存在全局变量的概念。
static变量在第一次使用的时候初始化,但只会有一份成员对象。
所以这里不仅可以调用,而且每一次调用都确实修改了x的值,也就是变化情况是这样的:
x=101
x=102
x=103
x=102

对于JVM内存配置参数:

-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3

其最小内存值和Survivor区总大小分别是()

正确答案: D 你的答案: D (正确)

A. 5120m,1024m
B. 5120m,2048m
C. 10240m,1024m
D. 10240m,2048m

解析:
-Xmx:最大堆大小
-Xms:初始堆大小
-Xmn:年轻代大小
-XXSurvivorRatio:年轻代中Eden区与Survivor区的大小比值
年轻代5120m, Eden:Survivor=3,Survivor区大小=1024m(Survivor区有两个,即将年轻代分为5份,每
个Survivor区占一份),总大小为2048m。
根据Generation-Collection算法(目前大部分JVM采用的算法),一般根据对象的生存周期将堆内存
分为若干不同的区域,一般情况将新生代分为Eden,两块Survivor
计算Survivor大小,Eden:Survivor=3,总大小为5120,3x+x+x=5120 --> x=1024
-Xms初始堆大小即最小内存值为10240m

下面有关jsp中静态include和动态include的区别,说法错误的是?

正确答案: D 你的答案: D (正确)
A. 动态INCLUDE:用jsp:include动作实现
B. 静态INCLUDE:用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面
C. 静态include的结果是把其他jsp引入当前jsp,两者合为一体;动态include的结构是两者独立,直到输出时才合并
D. 静态include和动态include都可以允许变量同名的冲突.页面设置也可以借用主文件的
解析:
动态INCLUDE用jsp:include动作实现它总是会检查所含文件中的变化,适合用于包含动态页面,并且
可以带参数。
各个文件分别先编译,然后组合成一个文件。
静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面 。先将文件的代码被
原封不动地加入到了主页面从而合成一个文件,然后再进行翻译,此时不允许有相同的变量。
以下是对include两种用法的区别,主要有两个方面的不同 ;
1.执行时间上
<%@ include file="relativeURI"%> 是在翻译阶段执行
<jsp:include page="relativeURI" flush="true" /> 在请求处理阶段执行
2.引入内容的不同
<%@ include file="relativeURI"%>引入静态文本(html,jsp),在JSP页面被转化成servlet之
前和它融和到一起
<jsp:include page="relativeURI" flush="true" /> 引入执行页面或 servlet 所生成的应
答文本