笔试面试题三

61ServletContext对象是由谁创建的

servletcontext,叫SERVLET上下文,使用了单例模式,他的创建时有servlet容器创建的,在启动时就创建好了。

通过Config.getServletContext()或者继承了HTTPSERVLET的对象中调用THIS.GETSERVLETCONTEXT。

因为是单例模式,所以是共享的,也就是SERVLET间可以用它互相通信!


62Java中类加载的过程?类加载器?

http://www.ibm.com/developerworks/cn/java/j-lo-classloader/

加载器加载的是什么?.class文件!

是根据类名等信息找到文件生成对象的。就是反射创建对象的过程。

除此之外,ClassLoader还负责加载 Java 应用所需的资源,如图像文件和配置文件等。

基本上所有的类加载器都是 java.lang.ClassLoader类的一个实例

分这么几种:

根加载器BOOTSTRAP C++写的  加载系统的,比如JAVA.LANG.*

扩展类加载器EXTENSION jre/LIB/EXT  扩展的API

系统,应用加载器SYSTEM APPLICATION 在CLASSPATH中 加载应用的

自定义加载器,继承CLASSLOADER然后重写findClass方法,loadClass方法不建议重写以免破坏了父委托机制。




特别注意!!为了JVM的安全,采用父加载机制,会从根加载器开始找!!!以免你复写了STRING等!!


loadClass调用FINDCLASS,FINDCLASS找到后调用DEFINECLASS返回一个CLASS对象给LOADCLASS

http://blog.csdn.net/jiangwei0910410003/article/details/17733153


63SESSION共享

这个没接触过,因为公司用的是CAS,而CAS使用的是TICKET流程,服务器验证成功给客户端一个TICKET,客户端拿这个取同户名等信息放到自己的SESSION中。


64动态静态INCLUDE区别

<jsp:include page="included.jsp" flush="true" />
它总是会检查所含文件中的变化,适合用于包含动态页面,并且可以带参数 
<%@ include file="included.htm" %> 
静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面

65LINUX

ps -ef | grep 'XX'

kill -s 9 PID


66详述堆和栈,进程和线程的含义?

进程,竞争计算机资源的最小单位!他是一个活动的实体。程序是没有活动的实体,当计算机给了程序生命了,就成为了进程。

一个进程可包括许多线程,他使用进程的资源,线程作为进程的最小调度单位。

每启动一个程序就至少启动了一个进程,而一个进程至少包含一个线程。

我们上面说过JVM的内存有两种,堆和非堆,对是程序员使用的,非堆是JVM使用的。

那么栈就是非堆,它里面有什么呢?

http://my.oschina.net/u/1464779/blog/225590

存在栈中的数据是可以共享的,基本数据类型int, short, long, byte, float, double, boolean, char(注意, 
并没有string的基本类型)的数据变量都在栈里和对象的引用变量。包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中。

JAVA中有6个地方可以放数据

1寄存器,最快

2栈,速度仅次于寄存器

3堆

4静态存储 static

5常量池

以文本形式出现的符号引用,比如: 类和接口的全限定名; 字段的名称和描述符; 方法和名称和描述符。 虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用到常量的一个有序集和,包括直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。对于String常量,它的值是在常量池中的。而JVM中的常量池在内存当中是以表的形式存在的,对于String类型,有一张固定长度的CONSTANT_String_info表用来存储文字字符串值,注意:该表只存储文字字符串值,不存储符号引用。说到这里,对常量池中的字符串值的存储位置应该有一个比较明了的理解了。

在程序执行的时候,常量池会储存在Method Area,而不是堆中.

用new String()创建的字符串不是常量,不能在编译期就确定,所以new String()创建的字符串不放入常量池中,他们有自己的地址空间。
String 对象(内存)的不变性机制会使修改String字符串时,产生大量的对象,因为每次改变字符串,都会生成一个新的String。 java 为了更有效的使用内存,常量池在编译期遇见String 字符串时,它会检查该池内是否已经存在相同的String 字符串,如果找到,就把新变量的引用指向现有的字符串对象,不创建任何新的String 常量对象,没找到再创建新的。所以对一个字符串对象的任何修改,都会产生一个新的字符串对象,原来的依然存在,等待垃圾回收。
八种基本类型的包装类和对象池   java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用常量池,也即对象不负责创建和管理大于127的这些类的对象。


可以这么理解,

1常量池是什么?

答:存放常量的地方,好处是如果里面已经有了就直接指向而不重复创建。

2常量池有几种?

答:两种,静态常量池和运行时常量池。

静态常量池就是.class文件中的大部分内容,包括跟类相关的,方法相关的等信息。当JVM把类装载进来时,也把静态常量池载入到了内存,并放在了【方法区】

方法区由于不同JVM的实现差距挺大,HOTSPOT里就是PERMGEN SPACE,也就是永久代,但是JDK8已经移除了,换成了元数据区。

永久代也会被垃圾回收和触发垃圾回收。我们知道GC有MINOR GC和FULL GC,年老区满了会触发FULL GC,永久代满了也会。


在java 中,直接使用==操作符,比较的是两个字符串的引用地址,并不是比较内容。所以很多试题会通过==考察你对JVM存储的理解。


谈到这要注意一点,我们看到方法区中的常量池是用静态常量池而来。那么程序运行中会往常量池塞东西么?答案是不会,除非你手动塞。

.intern()

3常量池会放什么?

除了String还会放这些东西:

八种基本类型的包装类和对象池  java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用常量池,也即对象不负责创建和管理大于127的这些类的对象。 

4常量池的一些怪癖:

String ss7 = "H";

    String ss8 = "ello";

    String ss9 = ss7 + ss8;

    String ss1 = "Hello";

    String ss2 = "Hello";

    String ss3 = "Hel" + "lo";


此时SS1 ==SS3 ,SS1 != SS9

为什么?我也不知道。

http://www.cnblogs.com/iyangyuan/p/4631696.html


会放这些东西:直接常量(string,integer和floating point常量)和对其他类型,字段和方法的符号引用。

什么叫常量?就是运行时确定了的,比如你明写int i= 4;他是放在栈里的。INTEGER I = 5;这才是放在常量池里的。

我们平时关注最多的是STRING类型的数据,如果运行时确定了的,放在常量池。

当要新创建一个STRING的值跟常量池里的数据一样时,就直接指过去而不浪费空间了。



6非RAM存储



最后总结,栈速度快,放的是基本数据变量以及对象的引用变量,当超过这些变量的作用域后内存就会被释放。


  1)新生成的对象在Eden区完成内存分配
     2)当Eden区满了,再创建对象,会因为申请不到空间,触发minorGC,进行young(eden+1survivor)区的垃圾回收。(为什么是eden+1survivor:两个survivor中始终有一个survivor是空的,空的那个被标记成To Survivor)
     3)minorGC时,Eden不能被回收的对象被放入到空的survivor(也就是放到To Survivor,同时Eden肯定会被清空),另一个survivor(From Survivor)里不能被GC回收的对象也会被放入这个survivor(To Survivor),始终保证一个survivor是空的。(MinorGC完成之后,To Survivor 和 From Survivor的标记互换)
     4)当做第3步的时候,如果发现存放对象的那个survivor满了,则这些对象被copy到old区,或者survivor区没有满,但是有些对象已经足够Old(通过XX:MaxTenuringThreshold参数来设置),也被放入Old区
     5)当Old区被放满的之后,进行完整的垃圾回收,即 Full GC
     6)Full GC时,整理的是Old Generation里的对象,把存活的对象放入到Permanent Generation里。

上面这段话需要注意的很多,包括什么时候S1的对象会放到OLD,什么时候OLD的会放到永久代。



67JSP,forward,redirect

一个重定向,一个转发,转发地址栏不变,可以继续获得REQUEST里的数据。


68仅用O(1)的空间,将整数数组按奇偶数分成2部分,数组左边是奇数、右边是偶数.

一个指针从左向右扫第一个偶数,一个指针从右向左扫第一个奇数,如果左小于右,互换,继续扫,直到右大于左位置



69 GET POST 

长度,URL中是否显示,安全


70什么是unchecked exception,什么是checked exception?它们在代码中被抛出时,需要捕获或显示声明抛出么?

checked需要,因为继承自java.lang.Exception接口,我们知道这是由bootstrap类加载器加载的。

uncheck继承自java.lang.RuntimeException.


71手机号验证正则

^1[3|5|7|8|]\d{9}


72多个空格转一个

String s = "s  tr in  g";

        s = s.replaceAll(" +",""); //关键

        System.out.println(s);


73JAVA的反射

那天跟梦说了,实际上使用的不多,除了当初在JDBC里,更多的都隐含在框架中由框架去调用了。

关键就是在只传进来class文件的情况下,知道里面都有神马方法参数,各种信息,去创建这个对象并且赋值。而且像STRUTS和SPRING这种都是有配置文件的,可直接读配置文件。


74店中店形势的劣势

不想写这个的,但是都说被问到了,店中店顾名思义就是商店里的商店,所以在推广和品牌知名度上会有问题。管理上受制于人,且依托的是别人的客源和人流。过于依赖他人。


75在Java中Lock接口比synchronized块的优势是什么?你需要实现一个高效的缓存,它允许多个用户读,但只允许一个用户写,以此来保持它的完整性,你会怎样去实现它?

LOCK读写分离,更灵活。一个是JVM的一个是JDK1.5后加入的。

在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。管道方法不建议使用,阻塞队列方法在问题4已有描述,现只提供前两种实现方法。

  • wait()/notify()方法
  • await()/signal()方法
  • BlockingQueue阻塞队列方法
  • PipedInputStream/PipedOutputStream
http://www.ituring.com.cn/article/111835


lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。Java线程面试的问题越来越会根据面试者的回答来提问。我强烈建议在你去参加多线程的面试之前认真读一下Locks,因为当前其大量用于构建电子交易终统的客户端缓存和交易连接空间。


76为什么调用start()方法时会执行run()方法,而不能直接调用run()方法?

调用start()方法时,将会创建新的线程,并且执行在run()方法里的代码。但如果直接调用 run()方法,它不会创建新的线程也不会执行调用线程的代码。

wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。

77AWAIT SIGNAL
 Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,在阻塞队列那一篇博文中就讲述到了,阻塞队列实际上是使用了Condition来模拟线程间协作。
http://www.cnblogs.com/dolphin0520/p/3920385.html
 

78用Java编程一个会导致死锁的程序
一个线程 两个STATIC变量
一个标识变量
创建2个线程的对象
里面有顺序执行的2个if(),根据标识值不同执行其中一个
一个if对静态变量1同步,SLEEP后对静态变量2同步  这里用着2个静态变量当锁,这叫私有锁。
另一个if对静态变量2同步,SLEEP后对静态变量1同步。

79原子操作和volatile
原子操作即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,但不会阻塞线程(synchronized 会把别的等待的线程挂,或者说只是在硬件级别上阻塞了)。

Volatile一般情况下不能代替sychronized,因为volatile不能保证操作的原子性,即使只是i++,实际上也是由多个原子操作组成:

read i; inc; write i

假如多个线程同时执行i++,volatile只能保证他们操作的i是同一块内存,但依然可能出现写入脏数据的情况。如果配合Java 5增加的atomic wrapper classes,对它们的increase之类的操作就不需要sychronized。

http://www.cnblogs.com/dolphin0520/p/3920373.html

也就是当对一个VOLATILE的INT变量自增 ++的时候,就会发现脏读写了,因为++不是原子操作。

80唤醒一个阻塞的线程
用interrupt,无论SLEEP WAIT JOIN都可以

81不可变对象,为什么String不可变
String、BigDecimal以及包装器类型:Integer、Long、Short、Byte、Character、Boolean、Float和Double也是如此,你不能修改它们的值。
为什么?
因为他们在栈中的,栈中的数据哪来的?从静态CLASS文件放在方法区也就是永久代的或者程序调用intern加入的,他们是栈中除了基本数据类型之外的存在,他们是会有多个引用指向这个值的,如果他可变 ,那些对象做宝搞?

82Java中用到的线程调度算法
java的变量都在主存里,对于所有线程是共享的,而每个线程又都有自己的工作内存或者本地内存,保存的是主存中的部分变量的拷贝。线程操作的都是本地内存,线程之间无法直接通讯,都是通过主存。
CPU本身对各个线程的调度是随机的,JAVA里由JVM负责线程的调度,掉成调度就是根据规则分配CPU的使用权给各个线程,所以线程是CPU调度的最小单位,而进程是资源分配的最小单位。
线程调度有2种:分时和抢占式。
分时就是平均分配时间。轮流获得使用权。
而抢占式就是按照线程优先级。
JVM使用的是抢占式,而优先级相同的再去分时。
处以运行状态的线程会一直运行,除非让他放弃了CPU资源。

83JAVA中的引用
从JDK1.2开始,就分为了4中引用,强弱软虚
强 不会回收
软 资源不够回收
弱 只要发现了就回收
虚 与弱的区别在于需要和引用队列联合使用

84jsp内置对象
request
response
exception
config
out
session
application
page
pagecontext


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值