Oracle面试之行

    之前也是和同学做了一下Oracle的PAC测试,也没有怎么去想结果,但是在周六的晚上九点半接到电话,说今天要去面试- -,然后就翘了计算机组成去面试了,其实呢,面试官挺好的,主要我去的比较早,然后一个人挺无聊的,就看了一会kindle.     接下来说面试的内容了,总体来说,难度不是很难,但是很基础,有些内容以前是看到的,但是在这种情况下,一时间也没有想起来。。。不得不说是一个败笔。     第一个是英文的自我介绍,这是被人坑的,我之前问了一下进甲骨文的学长,他说,不需要进行英文面试,于是我就没有准备,然后,就悲剧了,。还好我的英文还没有想像中的那么烂,不过有一个很有趣的小插曲,就是中途我有一个单词不会拼,就是红外传感器,传感器是sensor但是红外我就不知到了,我就直接问面试官,红外怎么拼。。他说我也不知道-= =,于是就在这样的气氛中,过了,不过他会打断你,然后问几个问题,我很神奇的发现,我居然临时使用英文把我做离线地图的方法,和过程描述给他了。。它还真听懂了-= -。。。还知道,我是假装浏览器的行为爬下来的。。     接下来是技术面试了,就是一些基本的问题:         1.抽象类和接口的不同,什么时候使用继承,什么时候使用实现接口。新建一个ArrayList对象,这边考察了装箱和拆箱,还有范型编程,还有ArrayList和LinkedList的区别等等,这些都是小儿科,常规的题目。         2.描述一下配置环境变量的时候需要设置PATH,和CLASSPATH,这些都是干什么的。这个很简单,第一个是执行路径,第二个就是运行时寻找库的路径,这也没什么。         3.然后就是考察对JDK源码的理解,比如说Object的源码,我当时只说了toString(),hashCode(),本来还能说equals()的,结果最终还是没能想起来。然后回来看了一下源码,发现自己还是弱了。。。这是源码中的方法,这一点还是比较失败的。                  4.接下来是多线程的问题,不过可能是我和他的理解不是很一样,就是两个线程访问一个对象的时候,会不会读脏数据。我的理解转换成代码就是这样的:                  这样的输出很明显都是Mike,但是如果在线程之间加上Thread.sleep(1000);这样的话,结果就是Mike,Simon了,所以,对于这一点,我是这么理解的,但是好像对方不是很赞同。。因为我的理解是,线程中有缓冲,所有线程修改的值都会写入这个缓冲之中,然后会刷新回主存,有关这个问题,我在一篇文章里也提到过,就是《volatile不能保证线程同步》,所以不知道这个问题怎么样。         5.然后要求手写一个简单的算法,就是快速排序,我的代码中出现了一个溢出的bug,但是在描述过程中还是能把过程描述清楚的。         6.接着就是问,在hashcode()方法的返回值,我把这个和序列化搞混了,然后回答了long型= =,对方接着问这个函数的作用和功能。这个我只知道在hashmap和hashtable中作为一个索引。但是如果两个类的hashcode相同会发生什么。。这个我就不知道了- -,只能胡乱说了- -。于是我现在查了下资料,也写了代码验证了一下。         这是引用的结果:             在Object类中定义的几个hashCode约定如下:                 1. 在同一应用中,一个对象的hashCode函数在equals函数没有更改的情况下,无论调用多少次,它都必须返回同一个整数。                 2. 两个对象如果调用equals函数是相等的话,那么调用hashCode函数一定会返回相同的整数。                 3. 两个对象如果调用equals函数是不相等的话,那么调用hashCode函数不要求一定返回不同的整数。             我们在改写equals 和 hashCode 函数的时候,一定要遵守如上3条约定,在改写equals的同时也改写hashCode的实现,这样才能保证得到正确的结果。         然后期间穿插了几个hashcode的问题,这几个问题都没有回答的很好。         7.然后是简单的描述一下Java代码到执行的一个过程,我扯了下javac,和字节码,说了下字节码中间的内容,比如前几个字节是魔数cafebabe,然后是版本号,然后是常量池,然后再说道运行时的加载,和Java的内存模型,比如,方法区,堆区等,然后把HotSpot虚拟机的分代垃圾回收机制说了下,看起来还是很满意的,然后又提到了JIT,及时编译技术,我的回答也还可以。多亏了《深入理解JVM-周志明》的这本书,让我学到很多。         8.然后又是描述一下Spring的作用,这个我只回答了Spring MVC的功能 – -,这个真的是我不擅长的地方。。但是在他给的选择里,Maven,Tomcat中,Maven是个工具,没什么好说的,Tomcat现在正在看他的源代码,没有太深入。。也就之后Spring了= =,有点坑自己的意思。。         9.还有一个问题是关于HTTP协议的,我本来想从TCP/IP开始说起,但是他让我直接描述HTTP包,于是。。我就凭着印象说了几个,但是感觉还是不是很好,因为,我没有能够结合REST进行讲解,这一点,现在我也查了资料,同时也用自己的浏览器实验了一把,就是这样的HTTP:         …

近期几个调错的总结

    文如标题,最近的几个调试的笔记了。     第一个案例就是一个学长写的网关模块代码,代码很长,很乱,真的很乱- -,所以 也没有想去研读代码,直接上手测试不过的案例,开visualVM进行跟踪,这个例子就 是在一条连接进入到连接跪了这段时间,这个程序的cpu占用会到100%,然后我就看, 发现这个进程中并没有太多的线程,也没有过多的GC,所以暂时推算是出现了while的 死循环。因为这个学长的日志系统做的极端的糟糕,所以从他的日志信息中也得不到什么重要的信息,所以只能硬着头皮去看代码,终于找到了根源,其实还是很简单的,他在读取socket的数值的时候,使用的是一个!=null的判断语句这个语句是不行的,因为BufferedReader有个很神奇的功能就是把null值的字符串变成”null”,所以加上一个!**.equals(“null”),然后程序就过了。     第二个案例也是一个学长的Java程序,在服务器上跑着,突然就频繁GC了,最终,OutofMemoryError跪了。也是打开VisualVM,发现频繁的GC出现在Old区,初步可以判断是大对象申请过多,在阅读了代码之后,最终确定了是在数据库读取阶段使用了ResultSet,同时使用完之后并没有即使清理,导致对象创建过多同时多存在引用关系,导致系统不能及时GC,所以导致了内存溢出,知道这个问题之后,一切都简单了。     第三个案例就是一个同学找到我,说在配置SSH免登录的配置之后,登录依旧是需要密码,于是,我按照流程帮他走了一遍,发现问题依旧存在,于是初步推断是权限问题,然后看了下这位同学的home权限,发现是777.。。所以大家都懂了,将.ssh目录设为700,authorized_keys文件设为600,一切就正常了。     最后一个就是自己的心得,将Tomcat7整合进了我的IDE,方便阅读和调试代码了,可以在这个地方下载我做好的Tomcat7。         接下来,我的任务也就简单了,继续阅读Netty和Tomcat源代码,同时跟进我的Hadoop.

基于Netty实现WebSocket

Netty的作用 Netty在这边的作用是做一个中间件,主要负责的是消息的接受,还有消息的处理,通过NIO的方式。 因为Netty易于开发,性能,稳定性和灵活性,不妥协的方式来实现。 文件结构 |– WebSocketServer.java |– WebSocketServerHandler.java |– WebSocketServerPipelineFactory.java |– websocket.html 具体解说 WebSocketServer.java 这个类的主要作用是进行服务器的一些部署,还有进行bootstrap,这主要是在进行启动配置 在这边我们可以看到,我们将WebSocketServerPipelineFactory注册进入了Netty,即将Netty的默认处理逻辑设置为我们需要的Factory. WebSocketServerHandler.java 这个类主要是封装了我们的处理逻辑。 由于Netty封装了所有接受的消息,所以在书写处理逻辑的时候,我们只需要覆盖两个父类的方法就行。 WebSocketServerPipelineFactory.java 这是这三个类当中代码最少的类了,主要的作用就是配置pipeline. 我们可以看到最后的那个addLast,就是在给这个工厂类添加处理逻辑 websocket.html 这段代码就是一个JS的WebSocket的调用,非常基础的一个。 代码看看就知道了,不扯了。 体会 对于我的感觉,像这样的一个简单的WebSocket的程序,在Netty中部署了三个类。 但是,这三个类的分工很明确,基本上可以将业务逻辑,事件注册,开启服务区分开来,并且整个框架是基于Message的,也就是可以很好的解耦合。 另外,WebSocket,我觉得是今后的一个趋势,不管服务器使用那一种语言,必定需要面对十万上百万的Socket连接,传统的基于流的Socket形式必定会造成大量的性能浪费。 同时,考虑到苏州的那个可能的电梯项目,7.5万条长连接可能基于原来的方式将会使用多台服务器,而采用这个Netty的现有框架,可以很快的进行开发,而且在效率和性能上也会有很大的提升。

一个简单的Servlet容器

文件结构 |– HttpServer.java |– Request.java |– Response.java |– ServletProcessor.java |– StaticResourceProcessor.java |– IndexServlet.java 文件的作用 HttpServer.java 这个类的作用和之前的静态类的服务器作用一样,唯一不同的一点就是在区分静态请求和动态请求上。 不过这边也是有一些问题的,因为如果我们的路径并不是包含”servlet”,则这方法也失去了他的意义。 Request.java 这边需要注意的是,这边需要实现ServletRequest接口 这个类的主要的作用就是从用户的请求中获取数据,其他的,也就不在这个程序中进行获取了 Response.java 这个类的主要作用就是将数据写回客户端。代码什么的也就是同之前的,没什么新的。 ServletProcessor.java 这个类的就是一个ClassLoader。 StaticResourceProcessor.java 这个类的作用就是一个分发器,为了保持接口的统一都使用了process(Request, Response)。 个人感悟 这样的一个服务器的最中心的作用就是一个分发器,将用户的请求分发,按照静态文件和动态文件进行分类 然后,所谓的负载均衡,和分布式,都可以通过这个服务器进行转发。 通过写这个服务器也更加深的理解了HTTP协议。这一点下一篇文章继续写。 后续的问题 这上面的代码是有安全风险的,因为这样我们就把这个Request和Response的公有方法就暴露在程序员的视线里 一个比较好的解决办法就是适配器模式,在传达对象时,通过一个适配器将对外的接口固定,这样才能做到安全。

有关静态文件服务器的编写

详细代码在这:MikeDog 文件结构 |–HttpServer.java |–Request.java |–Response.java 具体作用 首先是三个类,一个是主要的Server类,然后是Request和Response类,后两个是HTTP协议中的两个用于反馈和接受的类。 Request中主要的方法就是从一个HTTP头中抽取出URI,也就是访问路径。代码如下: 主要是因为HTTP协议中的地址信息,以下是一个HTTP请求协议: 从中可以看到URI在第一行的两个空格之间,当然,上面的写法比较风骚,因为这样的写法很容易带来漏洞,因为如果URI并不是标准的,或者说,有人故意发送一个错误的URI,导致解析错误什么的。 然后看Response中的代码,主要也是写出的,因为从Request中取出目标名称之后就可以从定义的ROOT目录中寻找那个HTML文件,然后要做的就是读出来,写出去。 于是这就成了,其中new File(HttpServer.WEBROOT, request.getUri());,就是读取文件的代码 注意:在HTTP头中,有文件大小的描述,在写出去的时候需要注意修改。如下: 最后就是HttpServer了,他的作用就是建立Socket连接,然后交给Request解析,然后将结果写入Response. 下面的代码就是过程,简单易懂: 最后就是我没有想到的一点,也是学到的一个新的方面: 即通过这个方法来获取网站根目录 最终运行结果(浏览器中)