论坛首页 入门技术论坛

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

浏览 34554 次
精华帖 (2) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2014-09-25  
不知道书里面对jvm有无讲解啊 不过看前面的部分目录 还是很吸引我的
后面去买一本读读
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中去除了方法区,使用元空间来替代。您能不能介绍一下元空间,并且去除方法区而使用元空间,对类加载的影响,对垃圾回收的影响,对于以后实际的使用需要注意哪些方面?



关于你说的部分对象不是分配在堆上的问题,这个其实是非Java的对象,Java对象不会出现,有些经过Java对象包装后的底层对象会在C Heap中有空间(例如DirectByteBuffer,但是它的实体不是Java对象,Thread也是类似的,它在start()后也是使用native空间)。
JIT主要是运行时的优化策略,更多是代码段上,数据上不会做什么太大变化,实际对象里面放的就是数据嘛,代码段的优化有很多,有些是动态inline、压缩汇编指令、本地代码cache等。

接下来的问题在书上也有所体现,不过那些仅仅是代表个人看法,没有任何官方说明。
你下面提到了方法区的问题,也就是在永久代里头,大部分情况下认为够用就好,GC也不需要关注,这样GC扫描的空间自然会少一些,配置永久代一般够用就好,没必要配多大,因为配置大了也是浪费,对象常规情况下也不会跑这里面来,注意的是这块空间不是把应用中所有的类和jar中所有的类都装到内存中,而是你用到的相关的类才会被加载,且在通过ClassLoader中只加载一次,大部分应用中会发现永久代使用比较稳定,而且使用量也不多,如果发现使用比较低,可以将空间留给堆来使用,因为它大部分情况下就是够用就好。

不过Java里头越来越多的技术导致这块区域也会经常动态变化,包括方法区也是这样的,比较典型的就是字节码增强的技术,热部署等,它们会导致方法区有所变化,另外这个区域以前是在永久代里面,永久代的膨胀不仅仅取决于Class本身,例如String的intern()在1.6及以前的版本也会放入永久代,JDK 1.7先把这一块剥离出来了,因为永久代满的时候导致的是FULL GC,既然这块空间可变化,它就应当属于普通堆内存的特征。

其实在其它JVM中(也就是除Hotspot VM外),没有永久代的概念,就Hotspot VM有这玩意,其它很多JVM都比这个东西跑得好,你说的Java 8的元空间我还没有研究过,因此我不敢对任何细节妄下断言。敢说的就是Java目前的发展肯定是希望写代码的人越简单的写法来写代码,复杂度会越来越少。Java的GC肯定会越做越好的。加载的方式理论上不会有什么太大变化,只是存放的位置会变化,这些应当对开发者的使用来讲更加没有什么影响的。至于GC方式,我认为要么你说的元信息在GC层面是独立的(和永久代类似,但更细化了),要么和堆一致,也不会造成什么影响,因为这块空间本身很有限,加上G1的一些机制,垃圾优先原则,肯定是变好的,而不是让我们针对某个Java版本去改更多的代码,至少应该不会针对一些已经存在的特征大量修改代码,对于新特征是可以选择性利用,例如JDK 1.6的高级锁,JDK 1.7的fock join,程序中可以选择用老的方式还是新的方式,在内在机制发生一些细节改变,也通常可以选择性的,如果不具有选择性,那肯定是更佳的方案,就像底层的锁优化肯定是变好,所以升级JDK后在不需要改代码的情况下,锁的性能理论上就是比以前高,至少应该可以能持平,这个是我的理解。
0 请登录后投票
   发表时间:2014-09-25  
wangmuming1122 写道
你好,我有一个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之类的参数配置?


首先JVM参数的细节应该是通过其它方式来看,比较简单的就是通过jmap -heap就可以看到一些基本参数,还有一些是通过jstat -gccapacity、jinfo等可以看到,jinfo需要一定的版本支持。

启动参数其实有些时候并不是那么重要,因为运行时是可以动态调整的,如果就你的JVM来讲,应该是默认输出,还谈不上启动参数,有些参数没设置,不代表它没有值,而且启动参数有好几百个,所以反过来推启动参数意义并不是特别大,就你给出的日志来讲,Young空间第一句说明:
def new generation   total 6464K, used 115K [0x34e80000, 0x35580000, 0x35580000)
这个6464K其实有点点问题,实际值是你说的7M,也就是5760K+704K+704K,它算的空间是Eden+一个Survivor空间,这个默认启动是采用串行GC方式,很多输出都这个鸟样子,或许它认为实际使用的就这么多吧。

这个地址范围我不多说了,你也知道咋算出来的,Eden、S0、S1也比较明显了,Eden大概是S0或S1的8倍左右,这也与SurvivorRatio的默认值8匹配。

tenured generation   total 18124K, used 8277K [0x35580000, 0x36733000, 0x37680000)
   the space 18124K,  45% used [0x35580000, 0x35d95758, 0x35d95800, 0x36733000)

这个明显是-client模式下的串行GC启动,不过在64bit下的JVM没有串行client这个分支了,使用了不会报错,也没有警告,但是启动的依然是server级别的,这个启动应该是在32bit下用的。

tenured generation这个是串行GC中老年代回收的算法名称,也是串行GC的代名词,总共有18124K,这个和上面年轻代的显示不一样,这个也是串行GC比较恶心的日志地方,18124K是当前老年代的大小是0x36733000-0x35580000=18M,不过老年代最大的大小是0x37680000-0x35580000=33.7M左右,也就是-Xms和-Xmx是不同的值,或者只设置了其中之一,或直接采用JVM默认。加年轻代,-Xmx大概是在40M+的样子。

老年代的第二句描述了它的使用情况,通过计算也可以算出来确实是45%。


最后是永久代:
compacting perm gen  total 16384K, used 16383K [0x37680000, 0x38680000, 0x38680000)
永久代总共16384K(16M),使用了16383K,从数字上看永久代空间满了。


不过这些数字是JVM输出的日志,它是否存在什么问题不一定(这种问题发生过不止一次),尤其是这类GC日志的输出,仅仅通过这个日志还推断不出太多东西出来,在串行GC上的细节我看得并不多,能讲的大概如此,希望可以帮助你理解。再说下哈,目前看参数一般不是通过这种方式看的,呵呵!


0 请登录后投票
   发表时间:2014-09-25  
wangmuming1122 写道
不知道书里面对jvm有无讲解啊 不过看前面的部分目录 还是很吸引我的
后面去买一本读读



看了目录应该知道本书有地方是讲JVM的,第3章可以算是完全讲JVM的,第5章也算吧,其实书的前后文字之中贯穿JVM的一些东西理解,不过我并不是JVM的专家,所以在JVM的专业性上肯定有所差距,并且讲解JVM的书籍有专门的书籍,国际大师写得有,过内也有顶尖高手写过,还有JVM神一样的人物有虚拟机的各种内核介绍(如R大),因为他们是参与虚拟机开发的,深入程度领先我不知道多少光年。

我的书上写JVM有两个目的,一个是站在一个普通程序员的角度,我觉得差不多应该去了解哪些东西,会阐述JVM这个知识点可能会对写代码有什么认知,第一章讲到String、Integer、集合类有一个粗浅的说明,后面章节会有很多相对深入说明,我们是通过理解虚拟机,然后回归到一些代码场景,希望去帮助我们写代码,帮助我们更好的了解内在的一些机制基础上去写代码,或许写一些核心程序的时候不是在猜、应该,而是很有底气,相对自信一些,因为你闭着眼睛都知道大概是咋在运行。

第二个目的就是一个小的引导性,让大家对这个感兴趣,让你觉得它对你的程序是有帮助的,希望大家去学会注重原理,或许这些引导性的JVM知识,可以让你在这个方面深入造诣,因为这些JVM知识最多最多算是入门级别。前6章的知识我都希望读者能细心去看,至少通过几次阅读能看懂半多的内容,加以实践,就能有许多新的体会。
0 请登录后投票
   发表时间:2014-09-26  
在阅读样章,听说有书送,求书,不过看完觉得不错没送也会掏钱买
0 请登录后投票
   发表时间:2014-09-26  
sully_2008 写道
在阅读样章,听说有书送,求书,不过看完觉得不错没送也会掏钱买



这个我在问下出版社同学是否还有量,你可以先私信我下,大量送的话出版社的同学也招架不住,呵呵!
0 请登录后投票
   发表时间:2014-09-26  
xieyuNL 写道
sully_2008 写道
在阅读样章,听说有书送,求书,不过看完觉得不错没送也会掏钱买



这个我在问下出版社同学是否还有量,你可以先私信我下,大量送的话出版社的同学也招架不住,呵呵!


哈哈,已私信,只看了部分样章,觉得比单纯的工具类书有趣,自己是边看边跟着操作,有些知识以前也看过,感觉加深了影响,引起了自己的思考,总体感觉还不错
0 请登录后投票
   发表时间:2014-09-26  
sully_2008 写道
xieyuNL 写道
sully_2008 写道
在阅读样章,听说有书送,求书,不过看完觉得不错没送也会掏钱买



这个我在问下出版社同学是否还有量,你可以先私信我下,大量送的话出版社的同学也招架不住,呵呵!


哈哈,已私信,只看了部分样章,觉得比单纯的工具类书有趣,自己是边看边跟着操作,有些知识以前也看过,感觉加深了影响,引起了自己的思考,总体感觉还不错



谢谢你的支持,希望能够给你带来一些帮助,书的目的也是希望大家有更多的思考和探讨,与实践多结合,而不是为那个结果较真,我最害怕的就是某些小伙伴为结果较真,高手可能为结果较真就当我太low了,无所谓,初学者如果为结果较真可能就会被误入歧途,所以一直定位是工作时间不太久但渴望进步的人。
0 请登录后投票
   发表时间:2014-09-26  
能剧透一些Java特种兵 下 里面的内容吗?
下会包含那些内容?
0 请登录后投票
   发表时间:2014-09-26  
wangmuming1122 写道
能剧透一些Java特种兵 下 里面的内容吗?
下会包含那些内容?



没什么不可以的,下册的内容在上册的前言中就有的,本来是一本书的,没有什么上下册,主要是字数超出了出版社的要求好几倍,硬拆成上下册的,下册手稿和上册的手稿都是年初完成的,目前就上册和出版社修订了几次出版了,我主要看下这本书真的是否适合大家再考虑出下册,如果觉得上册写得烂的话,也少花点冤枉钱,呵呵!

前言部分在这个博客中有的:http://blog.csdn.net/xieyuooo/article/details/38612913
其中第3篇~第5篇就是属于下册内容。
简单说,下册是写的东西更多要虚一点,设计、实现、一些技术坑、一些技术小原理、思考、人际、沟通、量化成本、集群、分布式、程序员的心态等等。或许对比上册没多大吸引力,这也是上册更适合大众的原因。
0 请登录后投票
论坛首页 入门技术版

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