java开发考题——带答案

johnnyt.k 贡献于2017-06-15

作者 CE  创建于2010-11-15 01:12:00   修改者zzh  修改于2014-05-07 03:22:00字数7004

文档摘要:
关键词:

 开发人员A卷(答题时间60分钟) 姓名:____________________ 联系方式:________________ 一、单选题(每题4分,共7题) 1. 给定如下Java 程序代码片段,编译运行这段代码,结果是( B )。 2. 给定以下Java代码,这段代码编译运行后输出的结果是( C ) 3. 下面哪一个不是jquery对象访问的方法?( D ) 4. 以下代码,能正确创建并启动线程的有__D__? 5. 下面哪种不是jquery的选择器?( C ) 6. 下列输出结果是( C ) 7.十进制变量i的值为12,那么八进制的变量i的值为:__D___ 二、多选题(每题4分,共6题) 1.关于被私有访问控制符private修饰的成员变量,以下说法不正确的是:(ABD) 2. 对于一个body内存在两个form, 如下: 以下不能获取到正确值的是(IE下):(EF) 3. 要动态改变层中内容可以使用的方法有(AB) 4. 下列选项中,描述正确的是 ( AD ) 5. UML中哪些图表示系统行为? (ACEF) 6. 环境变量classpath有何作用?(AB) 三、简答题 1.Java反射机制的作用?(3分) 1)在运行时判断任意一个对象所属的类。 2)在运行时构造任意一个类的对象。 3)在运行时判断任意一个类所具有的成员变量和方法。 4)在运行时调用任意一个对象的方法 (列出三个即可) 2. 描述一下JVM加载class文件的原理机制? (3分) JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类。 3. 请简单描述Java的内存模型,并分析Java内存泄露、内存溢出问题的原因及解决思路。(4分) Java内存模型 按照官方的说法:Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。 JVM主要管理两种类型内存:堆和非堆,堆内存(Heap Memory)是在 Java 虚拟机启动时创建,非堆内存(Non-heap Memory)是在JVM堆之外的内存。 简单来说,堆是Java代码可及的内存,留给开发人员使用的;非堆是JVM留给自己用的,包含方法区、JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码。 JVM 内存包含如下几个部分: · 堆内存(Heap Memory): 存放Java对象 · 非堆内存(Non-Heap Memory): 存放类加载信息和其它meta-data · 其它(Other): 存放JVM 自身代码等 在JVM启动时,就已经保留了固定的内存空间给Heap内存,这部分内存并不一定都会被JVM使用,但是可以确定的是这部分保留的内存不会被其他进程使用,这部分内存大小由-Xmx 参数指定。而另一部分内存在JVM启动时就分配给JVM,作为JVM的初始Heap内存使用,这部分内存是由 -Xms 参数指定。 详细配置文件目录:eclipse/eclipse.ini 默认空余堆内存小于40%时,JVM 就会增大堆直到-Xmx 的最大限制,可以由 -XX:MinHeapFreeRatio 指定。  默认空余堆内存大于70%时,JVM 会减少堆直到-Xms的最小限制,可以由 -XX:MaxHeapFreeRatio 指定,详见 可以通过 -XX:MaxPermSize 设置Non-Heap大小,详细参见我的百度博客 Java内存泄露、内存溢出问题 为了判断Java中是否有内存泄露,我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中,程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外),所有的对象都在堆 (Heap)中分配空间。另外,对象的释放是由GC决定和执行的。在Java中,内存的分配是由程序完成的,而内存的释放是有GC完成的,这种收支两条线的方法确实简化了程序员的工作。但同时,它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为,GC为了能够正确释放对象,GC必须监控每一个对象的运行状态,包括对象的申请、引用、被引用、赋值等,GC都需要进行监控。 监视对象状态是为了更加准确地、及时地释放对象,而释放对象的根本原则就是该对象不再被引用。 为了更好理解GC的工作原理,我们可以将对象考虑为有向图的顶点,将引用关系考虑为图的有向边,有向边从引用者指向被引对象。另外,每个线程对象可以作为一个图的起始顶点,例如大多程序从main进程开始执行,那么该图就是以main进程顶点开始的一棵根树。在这个有向图中,根顶点可达的对象都是有效对象,GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意,该图为有向图),那么我们认为这个(这些)对象不再被引用,可以被GC回收。 以下,我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻,我们都有一个有向图表示JVM的内存分配情况。以下右图,就是左边程序运行到第6行的示意图。 Java使用有向图的方式进行内存管理,可以消除引用循环的问题,例如有三个对象,相互引用,只要它们和根进程不可达的,那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高,但是效率较低。另外一种常用的内存管理技术是使用计数器,例如COM模型采用计数器方式管理构件,它与有向图相比,精度行低(很难处理循环引用的问题),但执行效率很高。 内存泄露解决思路 分析内存泄露的一般步骤       如果发现Java应用程序占用的内存出现了泄露的迹象,那么我们一般采用下面的步骤分析 1. 把Java应用程序使用的heap dump下来 2. 使用Java heap分析工具,找出内存占用超出预期(一般是因为数量太多)的嫌疑对象 3. 必要时,需要分析嫌疑对象和其他对象的引用关系。 4. 查看程序的源代码,找出嫌疑对象数量过多的原因。 具体内容参考如下: dump heap       如果Java应用程序出现了内存泄露,千万别着急着把应用杀掉,而是要保存现场。如果是互联网应用,可以把流量切到其他服务器。保存现场的目的就是为了把 运行中JVM的heap dump下来。      JDK自带的jmap工具,可以做这件事情。它的执行方法是: Java代码 1. jmap -dump:format=b,file=heap.bin    jmap -dump:format=b,file=heap.bin     format=b的含义是,dump出来的文件时二进制格式。     file-heap.bin的含义是,dump出来的文件名是heap.bin。     就是JVM的进程号。     (在linux下)先执行ps aux | grep java,找到JVM的pid;然后再执行jmap -dump:format=b,file=heap.bin ,得到heap dump文件。 analyze heap       将二进制的heap dump文件解析成human-readable的信息,自然是需要专业工具的帮助,这里推荐Memory Analyzer 。     Memory Analyzer,简称MAT,是Eclipse基金会的开源项目,由SAP和IBM捐助。巨头公司出品的软件还是很中用的,MAT可以分析包含数亿级对 象的heap、快速计算每个对象占用的内存大小、对象之间的引用关系、自动检测内存泄露的嫌疑对象,功能强大,而且界面友好易用。     MAT的界面基于Eclipse开发,以两种形式发布:Eclipse插件和Eclipe RCP。MAT的分析结果以图片和报表的形式提供,一目了然。总之个人还是非常喜欢这个工具的。下面先贴两张官方的screenshots:     言归正传,我用MAT打开了heap.bin,很容易看出,char[]的数量出其意料的多,占用90%以上的内存 。一般来说,char[]在JVM确实会占用很多内存,数量也非常多,因为String对象以char[]作为内部存储。但是这次的char[]太贪婪 了,仔细一观察,发现有数万计的char[],每个都占用数百K的内存 。这个现象说明,Java程序保存了数以万计的大String对象 。结合程序的逻辑,这个是不应该的,肯定在某个地方出了问题。  顺藤摸瓜      在可疑的char[]中,任意挑了一个,使用Path To GC Root功能,找到该char[]的引用路径,发现String对象是被一个HashMap中引用的 。这个也是意料中的事情,Java的内存泄露多半是因为对象被遗留在全局的HashMap中得不到释放。不过,该HashMap被用作一个缓存,设置了缓 存条目的阈值,导达到阈值后会自动淘汰。从这个逻辑分析,应该不会出现内存泄露的。虽然缓存中的String对象已经达到数万计,但仍然没有达到预先设置 的阈值(阈值设置地比较大,因为当时预估String对象都比较小)。      但是,另一个问题引起了我的注意:为什么缓存的String对象如此巨大?内部char[]的长度达数百K。虽然缓存中的 String对象数量还没有达到阈值,但是String对象大小远远超出了我们的预期,最终导致内存被大量消耗,形成内存泄露的迹象(准确说应该是内存消 耗过多) 。      就这个问题进一步顺藤摸瓜,看看String大对象是如何被放到HashMap中的。通过查看程序的源代码,我发现,确实有String大对象,不 过并没有把String大对象放到HashMap中,而是把String大对象进行split(调用String.split方法),然后将split出 来的String小对象放到HashMap中 了。  这就奇怪了,放到HashMap中明明是split之后的String小对象,怎么会占用那么大空间呢?难道是String类的split方法有问题?  查看代码 4. 关系型数据库与非关系型数据库的区别,各用在什么什么场景(3分) 基于关系模型建立的数据库称为关系数据库,其通常是有若干个有着一定联系的表组成。 对应于一个关系数据库模式的所有关系的集合称为关系数据库,关系数据库模式是数据的型的表示, 而关系数据库则是数据的值得表示。关系模型指实体与实体之间存在各种联系, 比如主外键关系,各种约束,以及关系操作。最简单的理解就是可以进行关系操作的数据库即为关系型数据库, 关系操作主要有:增、删、改、查、连接、与、或、非、模糊查询等。 非关系型数据库: a.使用松耦合类型,可扩展的数据模式来对数据进行逻辑建模(Map,列,文档,图表等),而不是使用固定的关系模式元组来构建数据模型 b.以遵循于CAP定理(能保证在一致性,可用性和分区容忍性三者中达到任意两个)的跨多节点数据分析模型而设计,支持水平伸缩 这意味着对于数据中和动态供应(在生产集群中透明地加入/删除节点)的必要支持,也即弹性. c.拥有在磁盘或内存中,或者在这两者中都有的,对数据持久化的能力,有时候还可以使用可热插拔的定制存储 d.支持多种的Non-SQL接口(通常多于一种)来进行数据访问 5. 请使用Java语言实现多线程模式下的生产者与消费者问题(7分) 参考代码如下: /* * 这是一个与多线程有关的以生产者消费者问题为原型的Java程序源码。 * 为了体验notify和notifyAll方法,我尝试开启十个生产者和五个消费者线程,对大小为8的缓冲区进行操作,要做到缓冲区产品达到8的时候,生产者线程阻塞,直到消费者线程减少缓冲区的产品数量,并对阻塞进程进行唤醒。 * 可现在的问题是,当生产者向缓冲区放入8个产品后,wait()方法并没有使生产者线程们停住,对此表示很疑惑。 * */ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class myProducer implements Runnable { private myProAndCon mpc; myProducer( myProAndCon mpac ){ this.mpc = mpac; } public void run() { try { while(!Thread.interrupted()) { //生产者互斥 synchronized (this){ //静态计数值达到上限,则wait()阻塞,等待被消费者线程唤醒 while ( mpc.get() >= 8 ) { System.out.println(mpc.get()); wait(); } } Thread.sleep(100); //未发生阻塞时,向缓冲区内放入产品,增加计数值,并唤醒所有阻塞的消费者线程 synchronized ( mpc.c ){ System.out.println("[ P ] The number is " + mpc.inc() ); mpc.c.notifyAll(); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class myConsumer implements Runnable { private myProAndCon mpc; myConsumer( myProAndCon mpac ){ this.mpc = mpac; } public void run() { try { while(!Thread.interrupted()) { //消费者互斥 synchronized ( this ) { //当缓冲区无产品时,消费者线程阻塞,等待被生产者线程唤醒 while ( mpc.get() <= 0 ) wait(); } Thread.sleep(3000); //未发生阻塞时,从缓冲区取出产品,减少计数值,并唤醒所有阻塞的生产者线程 synchronized (mpc.p){ System.out.println("[ C ] The number is " + mpc.dec() ); mpc.p.notifyAll(); } } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public class myProAndCon { public final int S = 8; //缓冲区计数器(静态)以及对其进行的三个synchronized操作 volatile private static int counter = 0; synchronized static int inc(){ return ++ counter; } synchronized static int dec(){ return counter -= 2; } synchronized static int get(){ return counter; } //构造两个对象,作为开启线程的参数 public myConsumer c = new myConsumer(this); public myProducer p = new myProducer(this); private ExecutorService exec = Executors.newCachedThreadPool(); public myProAndCon(){ //打开十个生产者线程 for ( int i = 0 ; i < 10 ; i ++ ) exec.execute(p); //打开五个消费者线程 for ( int i = 0 ; i < 5 ; i ++ ) exec.execute(c); } //主函数调用myProAndCon类构造方法,开始执行各个线程 public static void main(String[] s) { new myProAndCon(); } } 四、Sql查询题,数据库是Oracle或Mysql(任选一种) (13分) 表STUDENT(学生): 中文 编码 类型 学号 STUDENT_ID BIGINT 姓名 NAME VARCHAR(200) 年龄 AGE INT 性别 SEX INT 表SCORE(成绩): 中文 编码 类型 学号 STUDENT_ID BIGINT 课程名 SUBJECT VARCHAR(200) 成绩 SCORE INT 1. 先按照性别分组,查询男女学生的平均年龄。(3分) SELECT SEX, AVG(AGE) FROM STUDENT GROUP BY SEX 2. 用Sql找出姓名有重名的学生。(3分) SELECT * FROM SUTDENT GROUP BY NAME HAVING COUNT(*)>1 或 SELECT A.* FROM STUDENT A, STUDENT B WHERE A.STUDENT_ID != B.STUDENT_ID AND A.NAME=B.NAME 或 3. 把每个学生所有课程的总成绩加起来,然后查询出前10名。(3分) 4. 查出课程名是“数学”的所有成绩:(如某学生缺考时SCORE表无记录,成绩留空)(4分) 姓名 成绩 张三 90 李四 五、分析题 (答案写在反面) (15分) 网上书店有100万会员,每天产生订单约100万。设计实体关系图(Mysql或Oracle),实现: 1, 对图书基本信息、图书库存、会员、订单、订单明细的管理。(7分) 2, 图书种类共10万,在图书搜索框中,要求实现高性能的拼音匹配下拉列表。例如,当用户输入sf两个字母以上时,下拉出《算法导论》《私服通关宝典》等书籍。请简述实现方案要点。(8分)

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档