论坛首页 入门技术论坛

高手问答:Java老A带你全面提升Java单兵作战能力!

浏览 34495 次
精华帖 (2) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2014-09-23  
我最近有一个工作中遇到的问题,这段系统遗留代码是从AWS s3获取数据 按行读入
InputStream stream = getLogFileFromS3(filePath);//调用AWS sdk获取InputStream流,协议是HTTPS
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(stream));
while (bufferedReader.ready()) {
   String line = bufferedReader.readLine();
}

这段代码 在生产环境下是OK的。
但是在本地环境和测试环境下就不行了:while直接跳出。
测试环境和生产环境基本一致。
写了一个Jar模拟这段代码放到生产环境上单独运行,也有问题,

将连接协议改为Http就好了。

我猜测是HTTPS下InputStream.available()总是返回false
但是解释不了现在生产环境下可以运行..

可能跟实际项目联系比较紧密,能提供什么思路吗?

0 请登录后投票
   发表时间:2014-09-23  
神不为者人为之 写道
我最近有一个工作中遇到的问题,这段系统遗留代码是从AWS s3获取数据 按行读入
InputStream stream = getLogFileFromS3(filePath);//调用AWS sdk获取InputStream流,协议是HTTPS
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(stream));
while (bufferedReader.ready()) {
   String line = bufferedReader.readLine();
}

这段代码 在生产环境下是OK的。
但是在本地环境和测试环境下就不行了:while直接跳出。
测试环境和生产环境基本一致。
写了一个Jar模拟这段代码放到生产环境上单独运行,也有问题,

将连接协议改为Http就好了。

我猜测是HTTPS下InputStream.available()总是返回false
但是解释不了现在生产环境下可以运行..

可能跟实际项目联系比较紧密,能提供什么思路吗?



getLogFileFromS3()还没用过,最主要的是不清楚返回的流的实现类是那一个,看样子是从网络上读取的,ready()方法本身和available()不相关,这一点可以在其它网络读写的时候证明,这也是提供2个不同的方法的原因。至于思路我觉得除了看代码,可以先简单做两个小测试。
一个测试就是换个方式来读取,看下是否OK:
String result;
while((result = bufferedReader.readLine()) != null) {
    System.out.println(result);
}

如果结果依旧,就要排查下环境上的细节区别了,这个可能会涉及到环境中很细的部分,不是单纯的看看总体环境。

如果可以取到,就主要看下ready的代码到底是怎么写的,因为这个方法返回的输入流的实现类不清楚,因此源码就看不到了,也顺便查下,相应的实现类的版本是否一致。
0 请登录后投票
   发表时间:2014-09-24   最后修改:2014-09-24
xieyuNL 写道


你的问题比较多,呵呵,上面有一位哥已经帮忙回答,您可以参考下,我觉得写得挺好的。我站在我的角度再说说给你参考下哈:
(1)现在有非常多的编程语言,每种编程语言都有它独特之处与适用场景。不知您觉得JAVA语言的特点是什么,它在哪些场景下可以最大限度发挥语言自身的优势,哪些场景下表现一般?

这个问题我会说得比较抽象一点,其实我在书里面有些地方有提到(下册还会多一点),关于Java的语法特征其实不算是特点或它的优势,因为你的优势很容易被拷贝,呵呵!世界上只要你能做到的别人很快就能做到,包括跨平台之类的技术。

就Java来讲,它留下来更多的是一种传承,每一种语言的存在就带有它的使命并在传承它的血脉,直白点说就是它会为了某些问题而存在的语言,Java之初大家想设计万能的语言,但是发现做不到,不过它算是比较早期的面向对象语言,而且一直延续和传承。虽然它的成功不仅仅因为如此,不过它一直的一来的发展保持着Java一贯的”小清新”风格。我想Java目前解决最多的是企业级复杂的业务,它的语言本身就带着一种站在更高层次的思想来考虑问题的思路,不是基于实现来推导设计,而是基于设计来递推实现的思路。这些并不是其他语言做不到,只要掌握了这些思想,利用其他语言有能做到,只不过很多在这个语言传承下来的人,更加亲耐Java本身而已,它不是一些特征所取代的。

现实一点讲就是程序员蛮多,不过贵与不贵其实看能力以及招聘方是否看重能力。目前Java涉及到手机Android,Java WEB、大数据、NOSQL等领域,从极小到极大都有东西。每一个领域使用它都有它的缘由所在,Java也让程序员的思想集中在整体上或业务上。很多人喜欢拿C来比较,C确实性能很好,Java和他比性能基本是找死,除非是找写C代码极烂的人与写Java极好的人来比,不过这就没啥可比性了,呵呵!Java本身注重点不再这里,为啥还能搞搞大数据,高并发数据写入呢,其实在许多大数据的架构上,本身的复杂性希望落实到架构上,而不是很多细节处理,另外在分布式基础上,网络延迟基本就会达到毫秒级别,它很少会去探讨分布式整体方案上的微妙级别的区别,Java再慢这个level的时间单位它还是可以探讨的。

细说太多,而且容易引起群殴,呵呵!我从来不倡导Java有多么好,因为我不是“信徒”,我也从来不唱衰Java,因为我觉得它的血脉的确可以让一些的人在某些方面达成共识。



(2)作为一个JAVA高手,您觉得JAVA还需要增加哪些特性?现有的哪些特性您觉得不必有?

这个问题在前面一个问题基本回答,特征没有好与不好,只有在这种语言特征下它觉得是否该加或不该加,其实Java发展了这么多个版本,你会发现它除了内核的改变,也逐步加入了三方包的一些功能,例如Java 7就加入了文件处理的工具类,以前这些都是需要类似apache这些三方包来提供。

但是Java并没有把所有的东西囊括进来,因为那样Java就成了一个大杂烩,所以我觉得它的发展还是“小清新”路线,它会融入新的东西,但是是有选择性的,这些选择性通常具有较强的通用性,否则它为了一个特征去加入一种功能,这不是Java语言希望的发展方式。类似的例子还有很多,我就不在 一一列举。

总之,Java有的特征,我们要了解它的内在,没有的特征,可能三方包会去实现,如果还没有,我们如果对许多基础知识很了解,可以自己实现。基础特征没有必要太多,只要能够清晰的描述这门语言的正统基因就好,特征都是可以基于下面的层次逐步实现上来的,在社会发展的过程中,大家可能会发现许多共性的东西,Java本身在版本升级过程中也会纳入其中,这些不仅仅局限于Java语言的特征,还有它的外部插件,还有监控工具等。

如果非要说期望,那么Java运行的机制细节,Java能够提供相对完善的监控、定位、解决方案,就像Oracle的数据库产品一样。目前的许多监控是很多开源插件拼接而成,没有体系化的东西,很多问题需要多个工具来回配合才能知道到底是咋回事,如果在这些工具基础上,开放一些“安全的性能数据接口”或许这类似的需求就会一发不可收拾,站在类似产品的设计,就会要去归纳该咋做,不是一个一个小插件,而是一套维护管理的JVM的平台,甚至于维护一套JVM集群的平台。

还有,我也不是啥Java高手,只是一个使用Java编写代码的从业者,写这本书也是认为这些经验的分享或许可以帮助一些人去成长,我也在每天去学习很多东西,每天去提高自己的认识,所以我也强调自己的书中并不是完善、严谨的解释,甚至于不一定是完全正确的,我只是探讨出一些自己的认识和理解,我也希望读者能逐步有自己的认识和理解,从而练就自己的方法和思维习惯。



(3)现在JAVA的书籍好像提到并发时,基本上只是介绍多线程,而没有提到NIO,不知您对此怎么看?您在书中有介绍JAVA  NIO吗?

NIO有好处也有坏处,而且刚开始学的人如果直接迷恋NIO,就根本不知道为啥要用NIO,很多人是在BIO上有些痛不好解决,再用NIO才会释怀,它才有一种拨开云雾见青天的感觉。NIO是一种IO机制,它有它的应用场景,并非绝对好与不好,否则BIO就可以淘汰了,语法上干脆就别支持了。

多线程和IO方面有点关系,不过核心意义上不会强制扯到一起去,因为一个谈的是输入/输出,一个是线程调度,虽然最终探讨问题的时候也能跑一起去(例如上下文切换,利用多线程将IO密集度较高时,CPU空闲部分利用起来等)。

Java特种兵上册中有一部分是讲解Java NIO的,在第4章节Java通信会讲解,不过内容不多,会先说传统IO,再引导出来NIO、NIO 2.0,有个小例子,不过主要讲解原理,讲解他们的区别,说明一些场景。为啥没说太多,因为在这个领域我不是专家,在曾经做一些工作做IO选型时用过也测试过,但最终因为场景所限未选择NIO,因此谈及不上深入,因此只是让大家了解有这样一个东西存在。

(4)JAVA  NIO与Node.js有某些共通之处,如果二者让您选择,您会在什么情况下用JAVA  NIO,什么情况下用Node.js,为什么会有那样的取舍?


其实就像回答你的那位哥一样,语言不通而已,Java 1.4提出的NIO,是非阻塞IO还不是完全异步化编程模型,1.7的NIO 2.0基本可以算是异步编程了。因为写代码就跟写JS差不多,可以用异步回调、不断异步回调,也可以用Future,共通之处自然就是一些使用习惯和原理上,还有就是异步IO的应用场景肯定都是类似的。

什么情况下取舍其实不好说,IO层面要解决的问题类似,只是Java来写异步IO是符合一部分人的习惯的,有很多Java的中间件也是通过异步IO和非阻塞IO来做更好的效率,它最终是来配合Java实现一些东西。node.js是另外一套引擎,它可以做很多事情,不过你会发现它的特征更多面向WEB,甚至于有些时候可以拿来做负载均衡,它也可以基于V8引擎在服务器端把一些ajax的处理先处理掉,直接渲染给客户端,这样客户端就不用多次通信来渲染dom,对于网络不太好的客户端或许有些好处(当然要看场景,有些时候ajax渲染总体或许慢点,但是感知不一定会差)。总之具体问题具体分析,Java本身更适合干扩展和业务细节逻辑的事情,如果它在编写这个复杂中间层遇到IO瓶颈,也是可以用异步IO的,而node.js它在服务器端的侵入,主要是一些WEB组件(这主要是我个人的理解,不是权威说法,呵呵)。



(5)当大家张口数据结构,闭口算法时,我却感觉完成诸如管理系统之类的开发,数据结构与算法用得并不多。不知您工作中哪些地方用到这方面的知识?您觉得是否真的有必要下大力气去学好数据结构与算法,如果真想学好的话,有什么好的建议?

这样说,大部分Java从业者,尤其是初学者都不会用到,即使用到也不知道自己在用数据结构,因为大家只是为了将自己的“任务”完成,或许这个完成的标准还不一定真的是一个很好的标准,但是就是为了这个。

因此数据结构即使从身边走过,也未必知道,如果是这样,一般到2年多过后会在技术方向上有些吃力,很多人会在后续逐步走上管理甚至于纯管理路线,因为在大部分行业内确实搞清楚一些细节,对自己的发展也没有什么价值。

不过从我的角度来讲,如果想要长期发展技术本身,就得知道一些原理性的东西,从开始写代码不久就要有意识的去了解一些内在性的东西,刚开始不一定深入,但是一定要有意识去做。在了解原理的时候,就会结合到对于数据结构的认识,例如Java的集合类,就算你去了解String、StringBuilder也离不开这些。后面提到许多内存结构,JVM的对象结构,为什么要那样分配,都会有一些时间、空间上的探讨。当然你自身的志不在此,那么就无需强求,或者你的老板说这玩意一点都没有用,那么就要看你自己的想法了。在我工作头一两年也差不多这种情况,不过我当时是把研究技术作为一个技术屌丝的艺术追求和乐趣,这是我本人的性格所决定的。

其次,在本书样章的阅读中,其实有很多小意思的简单算法,用生活的例子来与计算机对应,其实就是在说,算法并不是想的那么难,至少大部分常规算法并没有想的那么难,而且它导致的结果就是我们思维方式的改变,让我们用更好的思路去解决问题,更清晰的知道解决问题的复杂度。如果提到这本书,其实算法和数据结构在字里行间,包括在提到一些计算机基础里面,很所思维方式都是算法衍生出来的(你也可以认为是这些思维方式衍生出来的算法,我们不用去追究历史,总之他们相辅相成)。

算法专门去学会很枯燥,一个是与实践结合,一个是注重思维方式以及计算机本身的情况,其实多想想,多拿笔出来画一画,就经常会有很多意想不到的收货。细节和例子我不能说太多了,说太多怕你会晕。


(6)JAVA是一门面向对象的语言,面向对象有GoF总结的著名设计模式,面向过程有什么经典的设计模式吗?也许在面向过程的领域不叫模式,总之就是有没有经典的设计思想或是说设计方法?这个问题好像有点儿偏离主题,不过我真的很好奇。

我下册会谈到一些设计模式,也会对比面向过程,不过面向过程有啥设计模式没有我还真说不上来,而且我本身对设计模式也不是那么“热恋”!在我看来设计模式是修为的展现形式,是高手和大师的内心总结,不过很多小伙伴会看得走火入魔,就像看一些规范一样,认为“什么就是对的,什么就是不对的”,设计模式本身是很抽象的一些东西,如果玩不明白,就在玩招式,招式再漂亮也还是招式,不知道招式该用在那里,这也是很多初学者以“编程思想”、“设计模式”常常挂在嘴边,认为永恒真理,但不知道为啥的被我认为是走火入魔,呵呵,或许这个词有点过,不过这算是一张模式病或强迫症。

要理解其实要一些经历,很多设计上的例子,比较抽象,一些西瓜、苹果、车子、拖拉机、小鸟、乌鸦,或许你能把例子背诵下来,但是项目中还是不知道咋用,还有不知道为啥那样用。

所以我一直不是特别推荐初学者看那些东西,或者说不推荐初学者死扣那些东西,你可以先知道有那些东西,但是要结合实践有一些自己的思考,最简单的突破口就是如果这个设计不用这样的设计模式,或者根本不用设计模式,会是啥样子的,会有啥好处与坏处。多去考虑考虑,你就会有很多体会。

这些思想类的书籍,对于每一个不同年龄段的程序员来讲,会有不同的理解层次,你有新的认识,就可以来翻阅这些书籍,其实这个时候是一种与大师之间心灵的沟通与完善自我,而不是被动的灌输。

其实很多思想是大师自己的经历所总结的,你的经历未必与他完全一致,你遇到的场景大师也未必完全遇到过,如果你在某些观点上有自己的见解,可以客观看待一些设计思想,和设计思想的场景,可以了解到大师本身的抽象目的,和通用场景,而并非完全绝对套用场景,我觉得就进步很大了,因为你可能在某方面的认识更高于设计模式的招式本身,说玄乎有点:在实际场景中将招式灵活变通出来才上乘(不过我目前也在摸索,依然没达到)。

(7)看一些著名框架的源码应该是一种很好的学习方法,不过有时感觉看着看着会模糊起来,因为感觉有些设计上太复杂了。不知您在看源码时有什么好的方法?

我在本书中会介绍一些学习框架源码的方法,或许可以帮助你,简单说,你看框架的目的和兴趣是什么,如果找不到看了就会搞忘,还有看源码通常不是一蹴而就的,你通常根据特征基于点去迭代看,多看几次就可以系统性的看一条线了。

这本书可能比较奇怪的是我在源码阅读时不会给一个全景图,也就是代码之间的调用关系,类之间的调用关系,为啥?因为我告诉你没啥意义,你阅读的源码可能根本就不是这些,你读的是自己所在领域的源码,还有更多其他的源码,我给这些关系一点意义都没有,我希望大家能养成一种阅读代码的习惯,最终这个图是自己总结出来的,我相信每个人总结出来的都不一样,因为理解的程度不同,而且这个图可细可粗,看每个人的习惯,源码讲解中的每一个点说清楚,需要自己理清楚思路,因为当你自己真正去阅读源码的时候,就没有人会给你这样一幅关系图了,给了也可能是某个版本的,定位问题还是要自己去理清楚。

(8)JAVA在设计中共用了哪些设计模式?比如:IO用了装饰器模式。我还想知道,您是通过哪些途径知道JAVA设计中使用了这些设计模式的?

这个我不想多说了,前面也有提到,关于Java常见的设计模式,网上有一大堆介绍!^_^

(9)学编程不可避免要接触到API,新手有时会感觉无从下手,不知如何快速获取自己想要的。甚至有时明明有,但因为找不到而自己重复造轮子,对此您有何建议?

用代码肯定会有API,一个是不要怕,Java最基本的API,就是常用的类嘛,有很多用不上的可以暂时不管,关键是玩了的就要玩明白。刚开始重复造造轮子我觉得很正常,很多人都会犯这个毛病,我在前言有介绍这类人,知道不对头了,自然会扭转思路,这通常是知道的东西深,但是知道的东西不多,相信自己写的代码,很自信,呵呵。不过这类人如果真搞出一些惊天动地的事情就不是重复造轮子了,至少他有意识去制造一些东西,而不仅仅是利用一些东西,通过这个过程也会去了解一些内容,了解别人是怎么做的,任何人都会经历,只是时间长短的问题,这没有对错之分,只是团队中有这样的情况要能够及时发现,并讲清楚为什么,它也可以学习别人写好的东西,对比自己那里做得不足,那里做得更好,怎么去扩展,就能让这个人也有所成长。

据说在谷歌,如果重复造轮子是会被鄙视的,呵呵,不过也要看具体情况,其实它的人员素养本身就很高,而且很多事情有一个统筹,大的规划和方向,而不是小产品的堆叠,如果环境和他差距很大,非要说控制重复制造,那也只能做到局部,因为大家都要解决自己工作中的问题,也要有自己的业绩。

(10)为了开发效率,也许要去找一些现成的框架来使用。我们到哪里去获取框架?获取框架后如何从众多的框架中去粗取精,舍劣存优,快速找到自己想要的框架?因为在筛选过程中,逐一对不了解的框架都去学习并编码实践,本身就要花费不少时间与精力。淘宝除了自己开发的框架以外,也用到不少开源的,不知你们是如何快速筛选的?

这算是一个经验的问题,常见的框架就那么一些,做WEB就那么一些常见的,做大数据也就那么些常见的,在每个领域刚开始都是听别人说,然后自己再去用,如何取舍要看自己的能力,有的人凭感觉,有的拍脑袋,觉得自己以前就用这个,肯定就用这个好(就像互联网程序员觉得写SQL应该越简单越好,因为效率可控,但传统行业并不是这样的观点),有的是前老板就是干这个出生的,你如果不用这个,他就控制不了你了,你也无法说出它有什么不好,或者他也根本不相信你,呵呵!

如果我去选择更多是考虑你要做什么,然后根据你的时间、人力、性能、稳定性、资金等情况来评估一个方案,开源框架本身不会决定太多业务上的发展,不过它可能会影响业务的发展速度和解决复杂业务问题的难度。还有可能会对性能有一定的影响,因此这些在前期会有一个短暂的沟通以做一个大方向的采纳。大方向定下来需要提出一些问题,大家来考虑如果出现什么什么,如何解决,如果方案对于这些问题大部分都是迎刃而解的,并非对比其它方案是更佳的,那就肯定选它了。

我们快速筛选已经形成公司内部的一种规范,大多数一样的,有些特征都会有一些场景描述,对于常规Java WEB层也就是那么一些东西,因为大多逐步开始统一化了,后台很多整体架构上的选型会有更多的考虑,一些负载均衡、分布式的方案、存储方案、缓存方案等等。

(11)如何实现JAVA与其它编程语言的互操作?如何调用其它语言封装的组件?如果确有需要,要同时用JAVA与其它语言协同,要如何让它们共同协作运行?

Java语言与其它语言相互操作,不爱护3种方式
一种是通过JNI来操作,例如Java就是基于C编写出来的,Java很多方法会调用所谓的本地方法就是调用C当中的方法,就是通过JNI来调用的,这种方式就是你要了解Java与底层语言之间规范,还有要保证底层语言的代码是没有问题的,如果你写的C、C++代码是有内存泄露、指针错误,那么Java调用的时候,就会有问题,甚至于crash掉,因为他们在运行时是同属一个进程的,还有此时你的Java程序不再跨平台,除非C部分的代码也像JRE本身那样为每个平台都写一套代码,否则开发人员的OS必须与线上环境也是一样的,不然没法在其它OS上跑程序。

一种方式就是进程调用,在同一台机器上,可以启动子进程的方式来启动其它语言的进程,相应的一些输入输出信息也可以做一些简单通信,不过这种依赖要想清楚的是,Java进程退出,这些子进程是否也要随着退出?

还有就是Java通信,通信通常就是跨语言的,除非一些Java本身的对象机制(如RMI),跨语言其实就类似数据+结构的传递方法,在对应的语言中根据结构有自己的方式来填充好数据。我们说一种非常简单的方式就是通过Socket与另一个进程通信,然后双方使用JSON进行传递,JSON是一种文本处理方式,因此它是对任何语言有效的,只要合适地处理字符集,就可以达到目的了。用XML也是类似的道理。

如何协作运行,其实是要看业务需求是什么,我说一个现实一点的例子,用Java去访问数据库,其实数据库就是一个C进程,当然你通过JDBC协议解析后去访问的,它的通信规范和字节传递方式都是JDBC驱动程序与MySQL Server约定好的,这是一种约定,也算是一种通常意义上的对外接口协议,当你自己去编写语言间的通信协议的时候,细节将由你自己决定。

其实就从广义上来讲,JSON、XML本身就是一种数据协议,它告知对方数据的格式,有那些数组,KEY是什么等等,对方会根据双方约定好的JSON数据格式,来读取JSON对应位置的数据,用以处理。通信协议只是更偏下面这一层而已。例如一个十分简单的案例就是在传递JSON的时候,先传递JSON的长度(字节长度),用4个字节来代表,对方读取4个字节后,就知道后续需要读多长了。类似在很多协议上都可以看到,很多文件下载前,也会在content信息上告知客户端文件的内容大小,因为server端可能对大文件不是一次性输出,分批输出的时候,有些浏览器在不知道内容大小的情况下就直接断开了,当然有的浏览器发现还有数据会继续接受,这里只是描述这样一个过程。

好了,问题多,我回答得更多,希望可以帮助到你那么一点点就好!




非常感谢如此耐心详细的回复,赞!  
0 请登录后投票
   发表时间:2014-09-25  
Java中的类型可以分成两种:基本类型,对象。Java中的对象一般分配在堆上,Java中有reference类型作为对象的引用,其保存的是对象在内存中的地址,一般内存中的地址都是一个整数,所以我可以把reference中保存的内容理解为一个数值吧?
==在比较基本类型时,判断它们的值是否相等;而在比较对象时,判断它们是否是同一个对象,其实==判断的应该是对象的引用,也就是两个数值。
那么,是不是可以这么说,==其实就是判断两个变量所代表数值是否相等?JVM在做==运算时,是怎么区分比较的是基本类型还是对象,或者根本就是如上说述,直接比较两个操作数的数值?
0 请登录后投票
   发表时间:2014-09-25  
楼上有人酸楼主写书赚钱,我就呵呵了。支持楼主。
0 请登录后投票
   发表时间:2014-09-25  
喻红叶 写道
Java中的类型可以分成两种:基本类型,对象。Java中的对象一般分配在堆上,Java中有reference类型作为对象的引用,其保存的是对象在内存中的地址,一般内存中的地址都是一个整数,所以我可以把reference中保存的内容理解为一个数值吧?
==在比较基本类型时,判断它们的值是否相等;而在比较对象时,判断它们是否是同一个对象,其实==判断的应该是对象的引用,也就是两个数值。
那么,是不是可以这么说,==其实就是判断两个变量所代表数值是否相等?JVM在做==运算时,是怎么区分比较的是基本类型还是对象,或者根本就是如上说述,直接比较两个操作数的数值?



你理解的整体上没问题,我细化下:
Java类型的对象肯定在堆上,不是一般在堆上分配。
引用如果是运行时在方法内部创建的,引用是直接在栈上的,如果对象内部的属性是一个对象,它保存的引用也是在对象内部。
引用基本可以认为是地址(内存虚拟地址),恩,你说得对地址肯定是数字(其实不论是不是整数,计算机内部也只有数字),因此引用内保存的也是数字。因此你的结论说比较数字是否相等的结论是OK的,因此运算量是很低的。

JVM运算==这个比较的时候,就如你所讲,是比较数字,所以和类型没啥关系,你可能会担心以下两个问题:
1、如果用一个对象和int值比较会不会相等?
int值与对象在==的时候,在编译阶段就通不过,所以你不用担心这个问题。

2、如果两个不同类型的对象比较会不会相等?
两个对象如果类型不同,那么肯定也不会是同一个对象,或者说不是同一块内存单元的对象,那么比较他们的地址也肯定不会相等。

如果非要说到运行中的类型,JVM肯定是需要知道的,因为普通类型和对象它在处理的时候是完全不同的方式,这些类型来自于你编译的Class中,都通常叫字节码,它是你的Java程序的翻译,翻译成更加适合计算机识别的格式,它会描述每一个属性、变量的类型细节和代码运行的逻辑细节。这个在第3章讲解字节码的时候会有一个小demo,虽然demo小,不过讲得还是比较详细,有兴趣可以看看。
0 请登录后投票
   发表时间:2014-09-25  
挺好的我也想去买一本读读
0 请登录后投票
   发表时间:2014-09-25  
peter2009 写道
挺好的我也想去买一本读读



谢谢你的支持,希望这本书能够给你一些帮助。
0 请登录后投票
   发表时间:2014-09-25  
xieyuNL 写道
喻红叶 写道
Java中的类型可以分成两种:基本类型,对象。Java中的对象一般分配在堆上,Java中有reference类型作为对象的引用,其保存的是对象在内存中的地址,一般内存中的地址都是一个整数,所以我可以把reference中保存的内容理解为一个数值吧?
==在比较基本类型时,判断它们的值是否相等;而在比较对象时,判断它们是否是同一个对象,其实==判断的应该是对象的引用,也就是两个数值。
那么,是不是可以这么说,==其实就是判断两个变量所代表数值是否相等?JVM在做==运算时,是怎么区分比较的是基本类型还是对象,或者根本就是如上说述,直接比较两个操作数的数值?



你理解的整体上没问题,我细化下:
Java类型的对象肯定在堆上,不是一般在堆上分配。
引用如果是运行时在方法内部创建的,引用是直接在栈上的,如果对象内部的属性是一个对象,它保存的引用也是在对象内部。
引用基本可以认为是地址(内存虚拟地址),恩,你说得对地址肯定是数字(其实不论是不是整数,计算机内部也只有数字),因此引用内保存的也是数字。因此你的结论说比较数字是否相等的结论是OK的,因此运算量是很低的。

JVM运算==这个比较的时候,就如你所讲,是比较数字,所以和类型没啥关系,你可能会担心以下两个问题:
1、如果用一个对象和int值比较会不会相等?
int值与对象在==的时候,在编译阶段就通不过,所以你不用担心这个问题。

2、如果两个不同类型的对象比较会不会相等?
两个对象如果类型不同,那么肯定也不会是同一个对象,或者说不是同一块内存单元的对象,那么比较他们的地址也肯定不会相等。

如果非要说到运行中的类型,JVM肯定是需要知道的,因为普通类型和对象它在处理的时候是完全不同的方式,这些类型来自于你编译的Class中,都通常叫字节码,它是你的Java程序的翻译,翻译成更加适合计算机识别的格式,它会描述每一个属性、变量的类型细节和代码运行的逻辑细节。这个在第3章讲解字节码的时候会有一个小demo,虽然demo小,不过讲得还是比较详细,有兴趣可以看看。

作者的回答非常好,解决了我的一个困惑,理解了==之后,就能能本质上区分==和equals了,而不仅仅是记住一条规则。
关于上面对象分配的问题,作者又纠正了我的一个错误,应该是由于我表述不严谨引起的。在虚拟机规范中描述到:所有的对象实例都分配在堆上。我上面的描述是指在HotSpot中,随着虚拟机优化技术的发展(JIT的发展),可能某些对象在实际运行时就不是分配在堆上了。
我想请求作者另外一个问题,关于元空间的。在HotSpot 1.7及以前的版本中,虽然Java虚拟机规范把方法区描述为堆的逻辑部分,但它还是把方法区作为单独的一块区域来实现的,而且每个类所对应的Class对象也是分配在方法区的(这也是一个特例)。但在Java 8中去除了方法区,使用元空间来替代。您能不能介绍一下元空间,并且去除方法区而使用元空间,对类加载的影响,对垃圾回收的影响,对于以后实际的使用需要注意哪些方面?
0 请登录后投票
   发表时间:2014-09-25  
你好,我有一个jvm相关的问题:
gc输出如下所示:
Heap
def new generation   total 6464K, used 115K [0x34e80000, 0x35580000, 0x35580000)
  eden space 5760K,   2% used [0x34e80000, 0x34e9cd38, 0x35420000)
  from space 704K,   0% used [0x354d0000, 0x354d0000, 0x35580000)
  to   space 704K,   0% used [0x35420000, 0x35420000, 0x354d0000)
tenured generation   total 18124K, used 8277K [0x35580000, 0x36733000, 0x37680000)
   the space 18124K,  45% used [0x35580000, 0x35d95758, 0x35d95800, 0x36733000)
compacting perm gen  total 16384K, used 16383K [0x37680000, 0x38680000, 0x38680000)
   the space 16384K,  99% used [0x37680000, 0x3867ffc0, 0x38680000, 0x38680000)
    ro space 10240K,  44% used [0x38680000, 0x38af73f0, 0x38af7400, 0x39080000)
    rw space 12288K,  52% used [0x39080000, 0x396cdd28, 0x396cde00, 0x39c80000)

请问如何根据上面的输出结果计算出最可能的启动JVM参数?

我能知道根据:
  def new generation   total 6464K, used 115K [0x34e80000, 0x35580000, 0x35580000)分析
  0x35580000 - 0x34e80000 = 7000000
  十进制为:7*16^5 /1024/1024 = 7M
  new generation 分配即为7M,其也是(eden space 5760K, from space 704K  to   space 704K,  相加之和)

能知道 -Xmn7m  -XX:+PrintGCDetails 请问根据上面的输出如何推测
-Xmx -Xms之类的参数配置?
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics