精华内容
下载资源
问答
  • jmap命令可以获取运行中jvm快照,从而离线分析,检查内存泄漏,检查一些严重影响性能对象的创建,检查系统中最多的对象,各种对象所占用的内存大小.可以使用jmap生成Heap Dump.什么是DumpDump是反应Java堆...

    jmap命令可以获取运行中的jvm的快照,从而离线分析,检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中最多的对象,各种对象所占用的内存大小.可以使用jmap生成Heap Dump.

    什么是堆Dump

    堆Dump是反应Java堆使用情况的内存镜像,其中主要包含系统信息,虚拟机属性,完整的线程Dump,所有类和对象的状态等。一般,在内存不足,GC异常等情况下,我们就会怀疑内存泄漏,这个时候就可以制作堆(Dump)来查询具体情况。

    常见的内存错误

    > outOfMemoryError 年老代内存不足。

    > outOfMemoryError:PermGen Space 永久代内存不足。

    > outOfMemoryError:GC overhead limit exceed 垃圾回收时间占用系统运行时间的98%或以上。

    jmap -heap pid

    查看java堆信息

    Attaching to process ID 18378, please wait...

    Debugger attached successfully.

    Server compiler detected.

    JVM version is 25.261-b12

    using thread-local object allocation.

    Parallel GC with 4 thread(s)

    Heap Configuration:

    MinHeapFreeRatio = 0 # JVM最小空闲比率

    MaxHeapFreeRatio = 100

    MaxHeapSize = 4164943872 (3972.0MB)

    NewSize = 87031808 (83.0MB)

    MaxNewSize = 1388314624 (1324.0MB)

    OldSize = 175112192 (167.0MB)

    NewRatio = 2

    SurvivorRatio = 8

    MetaspaceSize = 21807104 (20.796875MB)

    CompressedClassSpaceSize = 1073741824 (1024.0MB)

    MaxMetaspaceSize = 17592186044415 MB

    G1HeapRegionSize = 0 (0.0MB)

    Heap Usage:

    PS Young Generation

    Eden Space:

    capacity = 1314914304 (1254.0MB)

    used = 794405392 (757.6040191650391MB)

    free = 520508912 (496.39598083496094MB)

    60.41499355383087% used

    From Space:

    capacity = 36175872 (34.5MB)

    used = 23758320 (22.657699584960938MB)

    free = 12417552 (11.842300415039062MB)

    65.6744915506114% used

    To Space:

    capacity = 37224448 (35.5MB)

    used = 0 (0.0MB)

    free = 37224448 (35.5MB)

    0.0% used

    PS Old Generation

    capacity = 352321536 (336.0MB)

    used = 206117376 (196.56884765625MB)

    free = 146204160 (139.43115234375MB)

    58.502633231026785% used

    使用了Parallel GC垃圾收集器

    MinHeapFreeRatio 参数用来设置堆空间最小空闲比例,默认值是 0。当堆空间的空闲内存小于这个数值时,JVM 便会扩展堆空间。

    MaxHeapFreeRatio 参数用来设置堆空间最大空闲比例,默认值是 100。当堆空间的空闲内存大于这个数值时,便会压缩堆空间,得到一个较小的堆。

    当-Xmx 和-Xms 相等时MinHeapFreeRatio和MaxHeapFreeRatio 两个参数无效。

    MaxHeapSize 最大堆内存3972MB

    NewSize 新生代默认大小 83MB

    MaxNewSize 新生代最大大小为 1324MB

    OldSize 老年代大小 167MB

    NewRatio 新生代和老年代的大小比率 2

    SurvivorRatio 年轻代中Eden和Survivor的比率 8

    MetaspaceSize 元空间大小 20.796875MB

    CompressedClassSpaceSize 如果开启了-XX:+UseCompressedOops及-XX:+UseCompressedClassesPointers(默认是开启),则UseCompressedOops会使用32-bit的offset来代表java object的引用,而UseCompressedClassPointers则使用32-bit的offset来代表64-bit进程中的class pointer;可以使用CompressedClassSpaceSize来设置这块的空间大小

    MaxMetaspaceSize 最大元空间大小 1073741824

    G1HeapRegionSize G1收集器启用,一个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围从1M到32M,且是2的指数。

    jmap pid

    查看进程的内存映像信息,类似 Solaris pmap 命令

    使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较相似。

    [root@rumenz ~]# jmap 18378

    Attaching to process ID 18378, please wait...

    Debugger attached successfully.

    Server compiler detected.

    JVM version is 25.261-b12

    0x000056248b911000 8K /usr/local/jdk1.8/bin/java

    0x00007f35f8b2e000 487K /usr/local/jdk1.8/jre/lib/amd64/libfontmanager.so

    0x00007f35f8d91000 38K /usr/local/jdk1.8/jre/lib/amd64/libawt_headless.so

    0x00007f35f8f99000 741K /usr/local/jdk1.8/jre/lib/amd64/libawt.so

    0x00007f35f9669000 86K /usr/lib64/libgcc_s-4.8.5-20150702.so.1

    0x00007f35f987f000 276K /usr/local/jdk1.8/jre/lib/amd64/libsunec.so

    0x00007f36189ed000 110K /usr/local/jdk1.8/jre/lib/amd64/libnet.so

    0x00007f3618c04000 91K /usr/local/jdk1.8/jre/lib/amd64/libnio.so

    0x00007f361991f000 50K /usr/local/jdk1.8/jre/lib/amd64/libmanagement.so

    0x00007f363caee000 124K /usr/local/jdk1.8/jre/lib/amd64/libzip.so

    0x00007f363cd0a000 60K /usr/lib64/libnss_files-2.17.so

    0x00007f363cf1d000 226K /usr/local/jdk1.8/jre/lib/amd64/libjava.so

    0x00007f363d14c000 64K /usr/local/jdk1.8/jre/lib/amd64/libverify.so

    0x00007f363d35b000 42K /usr/lib64/librt-2.17.so

    0x00007f363d563000 1110K /usr/lib64/libm-2.17.so

    0x00007f363d865000 16698K /usr/local/jdk1.8/jre/lib/amd64/server/libjvm.so

    0x00007f363e85a000 2105K /usr/lib64/libc-2.17.so

    0x00007f363ec28000 18K /usr/lib64/libdl-2.17.so

    0x00007f363ee2c000 106K /usr/local/jdk1.8/lib/amd64/jli/libjli.so

    0x00007f363f044000 138K /usr/lib64/libpthread-2.17.so

    0x00007f363f260000 159K /usr/lib64/ld-2.17.so

    jmap -histo:live pid

    堆中对象统计

    其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个*前缀。如果指定了live子选项,则只计算活动的对象。

    [root@Server-i-b2l6uawirw ~]# jmap -histo:live 18378 | more

    num #instances #bytes class name

    ----------------------------------------------

    1: 221097 19915168 [C

    2: 220601 5294424 java.lang.String

    3: 44932 3954016 java.lang.reflect.Method

    4: 67973 3769400 [Ljava.lang.Object;

    5: 98145 3140640 java.util.HashMap$Node

    6: 115945 2782680 java.util.concurrent.atomic.AtomicLong

    7: 19301 2126520 java.lang.Class

    8: 61752 1976064 java.util.concurrent.ConcurrentHashMap$Node

    9: 14120 1665080 [Ljava.util.HashMap$Node;

    10: 8997 1548592 [B

    11: 15452 1236160 com.google.common.cache.LocalCache$Segment

    12: 34289 1097248 java.util.Hashtable$Entry

    13: 37325 895800 java.util.ArrayList

    14: 2899 790728 [Z

    15: 49080 785280 java.lang.Object

    16: 19315 772600 com.google.common.cache.AbstractCache$SimpleStatsCounter

    17: 21096 675072 java.lang.ref.WeakReference

    18: 16237 649480 java.lang.ref.SoftReference

    19: 13368 641664 java.util.HashMap

    20: 15945 637800 java.util.LinkedHashMap$Entry

    21: 114 588392 [F

    22: 18238 583616 java.util.concurrent.locks.ReentrantLock$NonfairSync

    23: 486 533312 [Ljava.util.concurrent.ConcurrentHashMap$Node;

    24: 16521 528672 java.lang.ref.ReferenceQueue

    25: 6928 498816 java.lang.reflect.Field

    26: 3863 494464 com.google.common.cache.LocalCache

    27: 7680 491520 java.net.URL

    28: 5948 475840 java.lang.reflect.Constructor

    29: 8359 463928 [I

    [B 代表 byte

    [C 代表 char

    [D 代表 double

    [F 代表 float

    [I 代表 int

    [J 代表 long

    [Z 代表 boolean

    jmap -clstats pid

    打印类加载信息

    -clstats是-permstat的替代方案,在JDK8之前,-permstat用来打印类加载器的数据

    打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。

    [root@rumenz ~]# jmap -clstats 18378

    Attaching to process ID 18378, please wait...

    Debugger attached successfully.

    Server compiler detected.

    JVM version is 25.261-b12

    finding class loader instances ..

    done.

    computing per loader stat ..done.

    please wait.. computing liveness.liveness analysis may be inaccurate ...

    class_loader classes bytes parent_loader alive? type

    3365 5881890 null live

    0x00000006cb8abb88 1 880 0x00000006c7c2a4c8 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006cafd0af0 1 878 0x00000006c8520248 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006c8600870 0 0 0x00000006c82362b8 dead hudson/ClassicPluginStrategy$DependencyClassLoader@0x00000007c0275308

    0x00000006c86a9878 81 74744 0x00000006c86a98e8 dead hudson/ClassicPluginStrategy$AntClassLoader2@0x00000007c0274dc8

    0x00000006ca739a60 1 880 0x00000006c7c2a4c8 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006cafceae8 1 880 0x00000006c7c2a4c8 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006cb541b40 1 880 0x00000006c7c2a4c8 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006cb75fb68 1 880 0x00000006c86b09b8 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006ca5f9a40 1 1474 null dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006cb07fb18 1 880 0x00000006c82bcba8 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006cb083b28 1 1474 0x00000006c7c2a4c8 dead sun/reflect/DelegatingClassLoader@0x00000007c000a0a0

    0x00000006c86ad848 8 8716 0x00000006c86ad8b8 dead hudson/ClassicPluginStrategy$AntClassLoader2@0x00000007c0274dc8

    0x00000006c8bde898 49 155511 0x00000006c8237a80 dead com/google/inject/internal/BytecodeGen$BridgeClassLoader@0x00000007c05f9028

    jmap -dump:format=b,file=dump.phrof pid

    生成堆转储快照文件

    这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用, 线上系统慎用。

    [root@rumenz ~]# jmap -dump:format=b,file=dump.hprof 18378

    Dumping heap to /root/dump.hprof ...

    Heap dump file created

    展开全文
  • jmap命令可以获取运行中jvm快照,从而离线分析,检查内存泄漏,检查一些严重影响性能对象的创建,检查系统中最多的对象,各种对象所占用的内存大小.可以使用jmap生成Heap Dump.什么是DumpDump是反应Java堆...

    jmap命令可以获取运行中的jvm的快照,从而离线分析,检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中最多的对象,各种对象所占用的内存大小.可以使用jmap生成Heap Dump.

    什么是堆Dump

    堆Dump是反应Java堆使用情况的内存镜像,其中主要包含系统信息,虚拟机属性,完整的线程Dump,所有类和对象的状态等。一般,在内存不足,GC异常等情况下,我们就会怀疑内存泄漏,这个时候就可以制作堆(Dump)来查询具体情况。

    常见的内存错误

    > outOfMemoryError 年老代内存不足。
    > outOfMemoryError:PermGen Space 永久代内存不足。
    > outOfMemoryError:GC overhead limit exceed 垃圾回收时间占用系统运行时间的98%或以上。

    jmap -heap pid

    查看java堆信息

    Attaching to process ID 18378, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.261-b12

    using thread-local object allocation.
    Parallel GC with 4 thread(s)

    Heap Configuration:
       MinHeapFreeRatio         = 0 # JVM最小空闲比率
       MaxHeapFreeRatio         = 100
       MaxHeapSize              = 4164943872 (3972.0MB)
       NewSize                  = 87031808 (83.0MB)
       MaxNewSize               = 1388314624 (1324.0MB)
       OldSize                  = 175112192 (167.0MB)
       NewRatio                 = 2
       SurvivorRatio            = 8
       MetaspaceSize            = 21807104 (20.796875MB)
       CompressedClassSpaceSize = 1073741824 (1024.0MB)
       MaxMetaspaceSize         = 17592186044415 MB
       G1HeapRegionSize         = 0 (0.0MB)

    Heap Usage:
    PS Young Generation
    Eden Space:
       capacity = 1314914304 (1254.0MB)
       used     = 794405392 (757.6040191650391MB)
       free     = 520508912 (496.39598083496094MB)
       60.41499355383087% used
    From Space:
       capacity = 36175872 (34.5MB)
       used     = 23758320 (22.657699584960938MB)
       free     = 12417552 (11.842300415039062MB)
       65.6744915506114% used
    To Space:
       capacity = 37224448 (35.5MB)
       used     = 0 (0.0MB)
       free     = 37224448 (35.5MB)
       0.0% used
    PS Old Generation
       capacity = 352321536 (336.0MB)
       used     = 206117376 (196.56884765625MB)
       free     = 146204160 (139.43115234375MB)
       58.502633231026785% used

    使用了Parallel GC垃圾收集器

    • MinHeapFreeRatio 参数用来设置堆空间最小空闲比例,默认值是 0。当堆空间的空闲内存小于这个数值时,JVM 便会扩展堆空间。
    • MaxHeapFreeRatio 参数用来设置堆空间最大空闲比例,默认值是 100。当堆空间的空闲内存大于这个数值时,便会压缩堆空间,得到一个较小的堆。

    当-Xmx 和-Xms 相等时MinHeapFreeRatio和MaxHeapFreeRatio 两个参数无效。

    • MaxHeapSize 最大堆内存3972MB
    • NewSize 新生代默认大小 83MB
    • MaxNewSize 新生代最大大小为 1324MB
    • OldSize 老年代大小 167MB
    • NewRatio 新生代和老年代的大小比率 2
    • SurvivorRatio 年轻代中Eden和Survivor的比率 8
    • MetaspaceSize 元空间大小 20.796875MB
    • CompressedClassSpaceSize 如果开启了-XX:+UseCompressedOops及-XX:+UseCompressedClassesPointers(默认是开启),则UseCompressedOops会使用32-bit的offset来代表java object的引用,而UseCompressedClassPointers则使用32-bit的offset来代表64-bit进程中的class pointer;可以使用CompressedClassSpaceSize来设置这块的空间大小
    • MaxMetaspaceSize 最大元空间大小 1073741824
    • G1HeapRegionSize G1收集器启用,一个Region的大小可以通过参数-XX:G1HeapRegionSize设定,取值范围从1M到32M,且是2的指数。

    jmap pid

    查看进程的内存映像信息,类似 Solaris pmap 命令

    使用不带选项参数的jmap打印共享对象映射,将会打印目标虚拟机中加载的每个共享对象的起始地址、映射大小以及共享对象文件的路径全称。这与Solaris的pmap工具比较相似。

    [root@rumenz ~]# jmap 18378
    Attaching to process ID 18378, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.261-b12
    0x000056248b911000      8K      /usr/local/jdk1.8/bin/java
    0x00007f35f8b2e000      487K    /usr/local/jdk1.8/jre/lib/amd64/libfontmanager.so
    0x00007f35f8d91000      38K     /usr/local/jdk1.8/jre/lib/amd64/libawt_headless.so
    0x00007f35f8f99000      741K    /usr/local/jdk1.8/jre/lib/amd64/libawt.so
    0x00007f35f9669000      86K     /usr/lib64/libgcc_s-4.8.5-20150702.so.1
    0x00007f35f987f000      276K    /usr/local/jdk1.8/jre/lib/amd64/libsunec.so
    0x00007f36189ed000      110K    /usr/local/jdk1.8/jre/lib/amd64/libnet.so
    0x00007f3618c04000      91K     /usr/local/jdk1.8/jre/lib/amd64/libnio.so
    0x00007f361991f000      50K     /usr/local/jdk1.8/jre/lib/amd64/libmanagement.so
    0x00007f363caee000      124K    /usr/local/jdk1.8/jre/lib/amd64/libzip.so
    0x00007f363cd0a000      60K     /usr/lib64/libnss_files-2.17.so
    0x00007f363cf1d000      226K    /usr/local/jdk1.8/jre/lib/amd64/libjava.so
    0x00007f363d14c000      64K     /usr/local/jdk1.8/jre/lib/amd64/libverify.so
    0x00007f363d35b000      42K     /usr/lib64/librt-2.17.so
    0x00007f363d563000      1110K   /usr/lib64/libm-2.17.so
    0x00007f363d865000      16698K  /usr/local/jdk1.8/jre/lib/amd64/server/libjvm.so
    0x00007f363e85a000      2105K   /usr/lib64/libc-2.17.so
    0x00007f363ec28000      18K     /usr/lib64/libdl-2.17.so
    0x00007f363ee2c000      106K    /usr/local/jdk1.8/lib/amd64/jli/libjli.so
    0x00007f363f044000      138K    /usr/lib64/libpthread-2.17.so
    0x00007f363f260000      159K    /usr/lib64/ld-2.17.so

    jmap -histo:live pid

    堆中对象统计 其中包括每个Java类、对象数量、内存大小(单位:字节)、完全限定的类名。打印的虚拟机内部的类名称将会带有一个*前缀。如果指定了live子选项,则只计算活动的对象。

    [root@Server-i-b2l6uawirw ~]# jmap -histo:live 18378 | more

     num     #instances         #bytes  class name
    ----------------------------------------------
       1:        221097       19915168  [C
       2:        220601        5294424  java.lang.String
       3:         44932        3954016  java.lang.reflect.Method
       4:         67973        3769400  [Ljava.lang.Object;
       5:         98145        3140640  java.util.HashMap$Node
       6:        115945        2782680  java.util.concurrent.atomic.AtomicLong
       7:         19301        2126520  java.lang.Class
       8:         61752        1976064  java.util.concurrent.ConcurrentHashMap$Node
       9:         14120        1665080  [Ljava.util.HashMap$Node;
      10:          8997        1548592  [B
      11:         15452        1236160  com.google.common.cache.LocalCache$Segment
      12:         34289        1097248  java.util.Hashtable$Entry
      13:         37325         895800  java.util.ArrayList
      14:          2899         790728  [Z
      15:         49080         785280  java.lang.Object
      16:         19315         772600  com.google.common.cache.AbstractCache$SimpleStatsCounter
      17:         21096         675072  java.lang.ref.WeakReference
      18:         16237         649480  java.lang.ref.SoftReference
      19:         13368         641664  java.util.HashMap
      20:         15945         637800  java.util.LinkedHashMap$Entry
      21:           114         588392  [F
      22:         18238         583616  java.util.concurrent.locks.ReentrantLock$NonfairSync
      23:           486         533312  [Ljava.util.concurrent.ConcurrentHashMap$Node;
      24:         16521         528672  java.lang.ref.ReferenceQueue
      25:          6928         498816  java.lang.reflect.Field
      26:          3863         494464  com.google.common.cache.LocalCache
      27:          7680         491520  java.net.URL
      28:          5948         475840  java.lang.reflect.Constructor
      29:          8359         463928  [I
    [B 代表 byte
    [C 代表 char
    [D 代表 double
    [F 代表 float
    [I 代表 int
    [J 代表 long
    [Z 代表 boolean

    jmap -clstats pid

    打印类加载信息 -clstats是-permstat的替代方案,在JDK8之前,-permstat用来打印类加载器的数据 打印Java堆内存的永久保存区域的类加载器的智能统计信息。对于每个类加载器而言,它的名称、活跃度、地址、父类加载器、它所加载的类的数量和大小都会被打印。此外,包含的字符串数量和大小也会被打印。

    [root@rumenz ~]# jmap -clstats 18378
    Attaching to process ID 18378, please wait...
    Debugger attached successfully.
    Server compiler detected.
    JVM version is 25.261-b12
    finding class loader instances ..
    done.
    computing per loader stat ..done.
    please wait.. computing liveness.liveness analysis may be inaccurate ...
    class_loader    classes bytes   parent_loader   alive?  type

         3365    5881890   null          live    
    0x00000006cb8abb88      1       880     0x00000006c7c2a4c8      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006cafd0af0      1       878     0x00000006c8520248      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006c8600870      0       0       0x00000006c82362b8      dead    hudson/ClassicPluginStrategy$DependencyClassLoader@0x00000007c0275308
    0x00000006c86a9878      81      74744   0x00000006c86a98e8      dead    hudson/ClassicPluginStrategy$AntClassLoader2@0x00000007c0274dc8
    0x00000006ca739a60      1       880     0x00000006c7c2a4c8      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006cafceae8      1       880     0x00000006c7c2a4c8      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006cb541b40      1       880     0x00000006c7c2a4c8      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006cb75fb68      1       880     0x00000006c86b09b8      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006ca5f9a40      1       1474      null          dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006cb07fb18      1       880     0x00000006c82bcba8      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006cb083b28      1       1474    0x00000006c7c2a4c8      dead    sun/reflect/DelegatingClassLoader@0x00000007c000a0a0
    0x00000006c86ad848      8       8716    0x00000006c86ad8b8      dead    hudson/ClassicPluginStrategy$AntClassLoader2@0x00000007c0274dc8
    0x00000006c8bde898      49      155511  0x00000006c8237a80      dead    com/google/inject/internal/BytecodeGen$BridgeClassLoader@0x00000007c05f9028

    jmap -dump:format=b,file=dump.phrof pid

    生成堆转储快照文件

    这个命令执行,JVM会将整个heap的信息dump写入到一个文件,heap如果比较大的话,就会导致这个过程比较耗时,并且执行的过程中为了保证dump的信息是可靠的,所以会暂停应用, 线上系统慎用。

    [root@rumenz ~]# jmap -dump:format=b,file=dump.hprof 18378
    Dumping heap to /root/dump.hprof ...
    Heap dump file created

    64efbd8ee582253d551e7ca6f5b303d8.png

    展开全文
  • java堆空间(内存

    千次阅读 2014-07-15 09:34:39
    Java程序开始运行时,JVM会从操作系统获取一些内存。JVM使用这些内存,这些内存的一部分就是堆内存堆内存通常存储地址的...大多数32位机、Sun的JVM上,Java的堆空间默认的大小为128MB,但也有例外,例如32
    当Java程序开始运行时,JVM会从操作系统获取一些内存。JVM使用这些内存,这些内存的一部分就是堆内存。堆内存通常在存储地址的底层,向上排列。当一个对象通过new关键字或通过其他方式创建后,对象从堆中获得内存。当对象不再使用了,被当做垃圾回收掉后,这些内存又重新回到堆内存中。
    

    在大多数32位机、Sun的JVM上,Java的堆空间默认的大小为128MB,但也有例外,例如在32未Solaris操作系统(SPARC平台版本)上,默认的最大堆空间和起始堆空间大小为 -Xms=3670K 和 -Xmx=64M。对于64位操作系统,一般堆空间大小增加约30%。但你使用Java 1.5的throughput垃圾回收器,默认最大的堆大小为物理内存的四分之一,而起始堆大小为物理内存的十六分之一。要想知道默认的堆大小的方法,可以用默认的设置参数打开一个程序,使用JConsole(JDK 1.5之后都支持)来查看,在VM Summary页面可以看到最大的堆大小。

    用这种方法你可以根据你的程序的需要来改变堆内存大小,我强烈建议采用这种方法而不是默认值。如果你的程序很大,有很多对象需要被创建的话,你可以用-Xms and -Xmx这两个参数来改变堆内存的大小。Xms表示起始的堆内存大小,Xmx表示最大的堆内存的大小。另外有一个参数 -Xmn,它表示new generation(后面会提到)的大小。有一件事你需要注意,你不能任意改变堆内存的大小,你只能在启动JVM时设定它。

    我们知道对象创建在堆内存中,垃圾回收这样一个进程,它将已死对象清除出堆空间,并将这些内存再还给堆。为了给垃圾回收器使用,堆主要分成三个区域,分别叫作New Generation,Old Generation或叫Tenured Generation,以及Perm space。New Generation是用来存放新建的对象的空间,在对象新建的时候被使用。如果长时间还使用的话,它们会被垃圾回收器移动到Old Generation(或叫Tenured Generation)。Perm space是JVM存放Meta数据的地方,例如类,方法,字符串池和类级别的详细信息。你可以查看“Java中垃圾回收的工作原理”来获得更多关于堆和垃圾回收的信息。

    当JVM启动时,使用了-Xms 参数设置的对内存。当程序继续进行,创建更多对象,JVM开始扩大堆内存以容纳更多对象。JVM也会使用垃圾回收器来回收内存。当快达到-Xmx设置的最大堆内存时,如果没有更多的内存可被分配给新对象的话,JVM就会抛出java.lang.outofmemoryerror,你的程序就会当掉。在抛出 OutOfMemoryError之前,JVM会尝试着用垃圾回收器来释放足够的空间,但是发现仍旧没有足够的空间时,就会抛出这个错误。为了解决这个问题,你需要清楚你的程序对象的信息,例如,你创建了哪些对象,哪些对象占用了多少空间等等。你可以使用profiler或者堆分析器来处理 OutOfMemoryError错误。”java.lang.OutOfMemoryError: Java heap space”表示堆没有足够的空间了,不能继续扩大了。”java.lang.OutOfMemoryError: PermGen space”表示permanent generation已经装满了,你的程序不能再装在类或者再分配一个字符串了。

    Java堆内存(heap memory)的十个要点:

    1. Java堆内存是操作系统分配给JVM的内存的一部分。

    2. 当我们创建对象时,它们存储在Java堆内存中。

    3. 为了便于垃圾回收,Java堆空间分成三个区域,分别叫作New Generation, Old Generation或叫作Tenured Generation,还有Perm Space。

    4. 你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。不要忘了在大小后面加上”M”或者”G”来表示单位。举个例子,你可以用 -Xmx256m来设置堆内存最大的大小为256MB。

    5. 你可以用JConsole或者 Runtime.maxMemory(), Runtime.totalMemory(), Runtime.freeMemory()来查看Java中堆内存的大小。

    6. 你可以使用命令“jmap”来获得heap dump,用“jhat”来分析heap dump。

    7. Java堆空间不同于栈空间,栈空间是用来储存调用栈和局部变量的。

    8. Java垃圾回收器是用来将死掉的对象(不再使用的对象)所占用的内存回收回来,再释放到Java堆空间中。

    9. 当你遇到java.lang.outOfMemoryError时,不要紧张,有时候仅仅增加堆空间就可以了,但如果经常出现的话,就要看看Java程序中是不是存在内存泄露了。

    10. 请使用Profiler和Heap dump分析工具来查看Java堆空间,可以查看给每个对象分配了多少内存。

    展开全文
  • 了解栈内存堆内存

    2019-09-29 07:10:07
    由于 java 有垃圾回收机制,所以往往不太会去关注栈堆的内存分配问题,直至OOM 一、了解栈堆概念 1、堆【存储对象创建实例】 ...在堆上分配空间是通过"new"等指令建立,堆是动态分配的内存大小,生存期也...

    由于 java 有垃圾回收机制,所以往往不太会去关注栈堆的内存分配问题,直至OOM

    一、了解栈堆概念

    1、堆【存储对象创建实例】

    1. 程序开始运行时,JVM从OS获取一些内存,部分是堆内存。堆内存通常在存储地址的底层,向上排列。
    2. 堆是一个"运行时"数据区,类实例化的对象就是从堆上去分配空间的;
    3. 在堆上分配空间是通过"new"等指令建立的,堆是动态分配的内存大小,生存期也不必事先告诉编译器;
    4. 与C++不同的是,Java自动管理堆和栈,垃圾回收器可以自动回收不再使用的堆内存;
    5. 缺点是,由于要在运行时动态分配内存,所以内存的存取速度较慢。

    2、栈【存放基本类型和引用类型】

    1. 先进后出的数据结构,通常用于保存方法中的参数,局部变量;
    2. 在java中,所有基本类型(short,int, long, byte, float, double,boolean, char)和引用类型的变量都在栈中存储;
    3. 栈中数据的生存空间一般在当前scopes内(由{…}括起来的区域;
    4. 栈的存取速度比堆要快,仅次于直接位于CPU中的寄存器;
    5. 栈中的数据可以共享,多个引用可以指向同一个地址;
    6. 缺点是,栈的数据大小与生存期必须是确定的,缺乏灵活性。

    3、总结

    1. Java堆内存是操作系统分配给JVM的内存的一部分。
    2. 当我们创建对象时,它们存储在Java堆内存中。
    3. 你可以通过用JVM的命令行选项 -Xms, -Xmx, -Xmn来调整Java堆空间的大小。
    4. 栈中存放的基本类型数据:short,int, long, byte, float, double,boolean, char
    5. 只要采用 new 的形式创建对象,那么就存储在 java 堆内存中。

    二、栈中的数据存储

    1、基本类型数据存储

    int a = 3;
    int b = 3;

    编译器先处理int a = 3;
    首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,
    然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。
    这样,就出现了a与b同时均指向3的情况。

    所以 a == b true

    2、包装类数据存储

    如Integer, Double, String等将相应的基本数据类型包装起来的类。
    这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。

    以String为例

    String是一个特殊的包装类数据。即可以用String str = new String("abc");的形式来创建,也可以用String str = "abc";的形式来创建。
    前者是规范的类的创建过程,即在Java中,一切都是对象,而对象是类的实例,全部通过new()的形式来创建。

    那为什么在String str = "abc";中,并没有通过new()来创建实例,是不是违反了上述原则?其实没有。

    关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:

    • a、先定义一个名为str的对String类的对象引用变量:String str;
    • b、在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象O,并将O的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象O。如果已经有了值为"abc"的地址,则查找对象O,并返回O的地址。
    • c、将str指向对象O的地址。
       值得注意的是,通常String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用(即:String str = "abc";既有栈存储,又有堆存储)。

    为了更好地说明这个问题,我们可以通过以下的几个代码进行验证。

    String str1 = "abc";
    String str2 = "abc";
    System.out.println(str1==str2); //true

    只有在两个引用都指向了同一个对象时才返回真值。str1与str2是否都指向了同一个对象)

    结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。

    3、总结

    (1). 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,我们创建了String类的对象str。

    担心陷阱!对象可能并没有被创建!唯一可以肯定的是,指向 String类的引用被创建了。
    至于这个引用到底是否指向了一个新的对象,必须根据上下文来考虑,除非你通过new()方法来显要地创建一个新的对象。
    因此,更为准确的说法是,我们创建了一个指向String类的对象的引用变量str,这个对象引用变量指向了某个值为"abc"的String类。
    清醒地认识到这一点对排除程序中难以发现的bug是很有帮助的。

    (2). 使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。
    而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。

    (3). 由于String类的immutable性质(因为包装类的值不可修改),当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

    4、实例

    String s = new String("abc") 创建了几个对象?

    首先我们要明白两个概念,引用变量和对象,对象一般通过new在堆中创建,s只是一个引用变量。

    答案2个。

    5、知识点

    我们可以用==判断一下两个引用变量是否指向了一个地址即一个对象

    转载于:https://www.cnblogs.com/niceyoo/p/11084391.html

    展开全文
  • 仔细看下面流程图,我们先来获取一个直观认识,然后再一点一点进行详细分析! 对象的创建(遇到一条 new 指令时)检查这个指令参数能否在常量池中定位到一个类...在堆中为新对象分配可用内存;将分配到的内存...
  • jmap查询JVM堆内存

    2020-12-02 23:34:40
    jmap命令可以获取运行中jvm快照,从而离线分析,检查内存泄漏,检查一些严重影响性能对象的创建,检查系统中最多的对象,各种对象所占用的内存大小.可以使用jmap生成Heap Dump. 什么是Dump Dump是反应Java...
  • java创建对象过程

    2019-11-27 16:48:29
    1.类加载检查 虚拟机遇到一条new指令...类加载通过后,接下来虚拟机将为新生对象分配内存内存大小在类加载检查之后就可以获取得到,分配内存主要是将一块完整的内存java堆中划分出来,分配方式有“指针碰撞”和...
  • jmap命令可以获得运行中的jvm的的快照,从而可以离线分析,以检查内存泄漏,检查一些严重影响性能的大对象的创建,检查系统中什么对象最多,各种对象所占内存的大小等等。可以使用jmap生成Heap Dump。 如果不想...
  • 仔细看下面流程图,我们先来获取一个直观认识,然后再一点一点进行详细分析!...类加载检查通过后,虚拟机将为新对象分配内存,此时已经可以确定存储这个对象所需的内存大小在堆中为新对...
  • Android获取内存信息

    2015-08-25 14:03:10
    android程序内存一般限制16M,当然也有24M的,而android程序内存被分为2部分:native和dalvik,dalvik就是我们平常说的java堆,我们创建的对象这里面分配的,而bitmap是直接native上分配的,对于内存的限制...
  • 一个Java对象在内存中包括3个部分:对象头、实例数据和对齐填充 1.1 对象头 Mark Word 状态标识。与虚拟机位数一样,一般64bit,32bit很少。下图是一个32位虚拟机Mark Word示例: 从对象头中可以获取到两点信息...
  • 内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的...
  • 一个类经过编译后通过一个类全限定名来获取其定义二进制字节流 ,然后将这个字节流所代表的的静态存储结构转化为方法区运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中这些数据...
  • 理解内存溢出

    2019-06-24 16:10:02
    内存泄漏的常见现象就是java.lang.OutOfMemoryError异常。这个异常常见抛出的情况为:当需要分配对象的时候,空间不足。这种情况下,垃圾收集器无法获取一个有效的空间来容纳一个新的对象,同时堆的大小也无...
  •  通过虚拟机内置的jstat指令获取内存各种和非堆的大小及其内存使用量  通过虚拟机内置jstack获取虚拟机线程的执行堆栈  统计、分析之后的数据封装为用于被监控数据对象,向各种渠道的数据观察者发送监控数据...
  • java 面试题 总结

    2009-09-16 08:45:34
    内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的...
  • java面试题

    2018-01-01 15:35:15
    通过Class对象来获取对象的类型。 49 66.1.3. 通过关键字instanceof或Class.isInstance()方法 49 67. 说出一些常用类,包,接口,请各举5个 50 68. XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有...
  • JAVA面试题最全集

    2010-03-13 13:09:10
    方法垃圾收集器将对象内存中清除出去之前做必要清理工作。这个方法是由垃圾收集器确定这个对象没有被引用时对这个对象调用。它是 Object 类中定义,因此所有类都继承了它。子类覆盖 finalize() ...
  • 操作系统(内存管理)

    热门讨论 2009-09-20 12:55:25
    如您所见,这个分配程序中,内存的释放使用了一个非常简单的机制,固定时间内完成内存释放。分配内存稍微困难一些。以下是该算法的略述: 清单 5. 主分配程序的伪代码 1. If our allocator has not been ...
  • 记一次OOM问题排查途径 本次一个模块对接一个业务方,业务方三个任务同时到达时出现OOM情况。... 查看java堆对象的相关信息,包含数量以及占用空间大小:jmap -histo 138254|head -15 当时nio两个...
  • 新生代垃圾回收频繁GC

    千次阅读 2019-03-18 15:49:01
    借助于java自带工具jmap -histo pid,可以快速多次获取虚拟机中当前各对象的实例数量以及占用内存大小。虽然获取内存dump文件也可以,但是耗时太长,另外机器可用内存太小,dump过程可能会有副作用。 数据...
  • 说明: 确定查询是否获取表级读取锁, 以防止包含该查询事务处理被提交之前更新任何对象读取。这种操作模式提供可重复读取, 并确保同一事务处理种对相同数据两次查询看到是相同值。 值范围: TRUE | ...
  • resin-jvm 调优

    2009-03-11 16:05:25
    –Xmx256m为控制新域的大小,可使用-XX:NewRatio设置新域在堆中所占的比例。 下面的命令把整个堆设置成128m,新域比率设置成3,即新域与旧域比例为1:3,新域为堆的1/4或32M: java –Xms128m –Xmx128m –XX:...
  • Spring面试题

    2015-05-06 07:19:39
    当Hibernate查询数据时候,数据并没有存在与内存中,当程序真正对数据操作时,对象才存在与内存中,就实现了延迟加载,他节省了服务器的内存开销,从而提高了服务器性能。 3.Hibernate中怎样实现类之间...
  • 【1】JVM1-10

    万次阅读 2019-11-23 22:35:03
    目录 知识点1:栈帧产生和销毁,什么时候出OOM错误? 知识点2:JVM优化 ...知识点8:创建对象在堆存放,新生代、年老代用算法 知识点9:永久代 知识点10:什么情况下栈溢出?堆溢出?...

空空如也

空空如也

1 2
收藏数 40
精华内容 16
关键字:

java获取对象在堆内存的大小

java 订阅