Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 监视JVM的非堆内存使用情况_Java_Performance_Memory_Jvm - Fatal编程技术网

Java 监视JVM的非堆内存使用情况

Java 监视JVM的非堆内存使用情况,java,performance,memory,jvm,Java,Performance,Memory,Jvm,由于堆或永久大小配置问题,我们通常处理OutOfMemoryError问题 但所有的JVM内存都不是permgen或heap。 据我所知,它也可能与线程/堆栈、本机JVM代码有关 但是使用pmap,我可以看到进程分配了9.3G,即3.3G堆外内存使用 我想知道监视和调整这个额外的堆外内存消耗的可能性是什么 我不使用直接堆外内存访问(默认情况下MaxDirectMemorySize为64m) JVM java version "1.7.0_09" Java(TM) SE Runtime Envir

由于堆或永久大小配置问题,我们通常处理OutOfMemoryError问题

但所有的JVM内存都不是permgen或heap。 据我所知,它也可能与线程/堆栈、本机JVM代码有关

但是使用pmap,我可以看到进程分配了9.3G,即3.3G堆外内存使用

我想知道监视和调整这个额外的堆外内存消耗的可能性是什么

我不使用直接堆外内存访问(默认情况下MaxDirectMemorySize为64m)

JVM

java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)
Tunning

-Xms=6g
-Xms=6g
-XX:MaxPermSize=128m

-XX:-UseGCOverheadLimit
-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSClassUnloadingEnabled

-XX:+OptimizeStringConcat
-XX:+UseCompressedStrings 
-XX:+UseStringCache 
内存映射:

vmstat

procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa
 1  0   1743    381      4   1150    1    1    60    92    2    0  1  0 99  0
免费

             total       used       free     shared    buffers     cached
Mem:          7986       7605        381          0          4       1150
-/+ buffers/cache:       6449       1536
Swap:         4091       1743       2348
顶部

top - 11:15:49 up 42 days,  1:34,  2 users,  load average: 1.44, 2.11, 2.46
Tasks: 104 total,   1 running, 103 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.5%us,  0.2%sy,  0.0%ni, 98.9%id,  0.4%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   8178412k total,  7773356k used,   405056k free,     4200k buffers
Swap:  4190204k total,  1796368k used,  2393836k free,  1179380k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                                                                                 
17833 jmxtrans  20   0 2458m 145m 2488 S    1  1.8 206:56.06 java                                                                                                                                    
 1237 logstash  20   0 2503m 142m 2468 S    1  1.8 354:23.19 java                                                                                                                                    
11348 tomcat    20   0 9184m 5.6g 2808 S    1 71.3 642:25.41 java                                                                                                                                    
    1 root      20   0 24324 1188  656 S    0  0.0   0:01.52 init                                                                                                                                    
    2 root      20   0     0    0    0 S    0  0.0   0:00.26 kthreadd             
...
df->tmpfs

Filesystem                1K-blocks     Used Available Use% Mounted on
tmpfs                       1635684      272   1635412   1% /run

我们面临的主要问题是:

  • 服务器有8G的物理内存
  • 一堆Solr只需要6克
  • 交换容量为1.5G
  • 交换性=0
  • 堆消耗似乎得到了适当的调整
  • 在服务器上运行:只有Solr和一些监控工具
  • 我们有一个正确的平均响应时间
  • 我们有时会有异常长的停顿,长达20秒
我猜暂停可能是交换堆上的完整GC,对吗

为什么有这么多的交换?

我甚至不知道这是否是使服务器交换的JVM,或者它是否是我看不见的隐藏的东西。也许是操作系统页面缓存?但不确定如果创建交换,操作系统为什么会创建页面缓存项

我正在考虑测试一些流行的基于Java的存储/NoSQL中使用的
mlockall
技巧,如ElasticSearch、Voldemort或Cassandra:check


编辑:

在这里,您可以看到max heap、used heap(蓝色)、used swap(红色)。这似乎有点关联

我可以从石墨中看出,有许多新的GC定期发生。还有一些CMS GC对应于图片的堆显著减少

暂停似乎与堆减少无关,但在10:00到11:30之间有规律地分布,因此我想它可能与ParNew GC有关


在负载测试期间,我可以看到一些磁盘活动和一些交换IO活动,当测试结束时,这些活动非常平静。

监视(并部分更改)JVM实例的运行时参数的一种非常方便的方法是VisualVM:

PS
(已删除)

PPS 我记得我不久前使用的另一个工具:。它以可视化的方式详细展示了JVM内存管理中发生的事情,这里有一些。非常强大,甚至可以与VisualVM中的插件集成(请参阅VisualVM主页上的插件部分)

购买力平价
我们有时会有异常长的暂停,最多20秒。[…]我猜暂停可能是交换堆上的完整GC,对吗?

是的,可能是这样。即使在未交换的堆上,完全GC也可能导致长时间的暂停。使用VisualVM,您可以监视~20秒暂停发生时是否发生完全GC。我建议在另一台主机上运行VisualVM,并通过将其连接到虚拟服务器上的JVM进程,以避免使用额外的负载伪造度量。您可以让该设置运行数天/数周,从而收集有关该现象的最终信息

根据当前信息,目前只有以下几种可能性:

  • 观察到的暂停与完整GC同时发生:JVM没有正确调优。您可以通过JVM参数,或者选择另一个GC算法/引擎来缓解这一问题(您是否尝试过GC?有关如何实现的更多信息,例如)
  • 观察到的暂停与JVM中的完整GC不一致:原因可能是物理虚拟主机。验证您的SLA(物理RAM中保证有多少虚拟RAM),并联系您的服务提供商,要求监控虚拟服务器
我应该提到VisualVM是Java附带的。JConsole也随Java一起提供,它比VisualVM更轻、更紧凑(但没有插件、没有评测等),但提供了类似的概述

如果为VisualVM/JConsole/VisualGC设置JMX连接目前过于复杂,您可以求助于以下java参数:
-XX:+PrintGC-XX:+printgimstamps-Xloggc:/my/log/path/gclogfile.log
。这些参数将导致JVM为每次GC运行向指定的日志文件写入一个条目。此选项也非常适合于长期分析,并且可能是JVM开销最小的选项


在反复思考你的问题之后:如果你想知道额外的3+GB是从哪里来的,这里有一个例子。我个人使用因子x1.5作为经验法则。

您的堆实际上使用了6.5 GB的虚拟内存(这可能包括perm gen)

您有一组使用64MB堆栈的线程。不清楚为什么有些使用默认的1MB,有些使用默认的1MB

总共有930万KB的虚拟内存。我只担心住户的人数

尝试使用
top
查找进程的驻留大小

你可能会发现这个程序很有用

    BufferedReader br = new BufferedReader(new FileReader("C:/dev/gistfile1.txt"));
    long total = 0;
    for(String line; (line = br.readLine())!= null;) {
        String[] parts = line.split("[- ]");
        long start = new BigInteger(parts[0], 16).longValue();
        long end = new BigInteger(parts[1], 16).longValue();
        long size = end - start + 1;
        if (size > 1000000)
            System.out.printf("%,d : %s%n", size, line);
        total += size;
    }
    System.out.println("total: " + total/1024);

除非您有一个使用内存的JNI库,否则我猜您有很多线程,每个线程都有自己的堆栈空间。我会检查你的线程数。您可以减少每个线程的最大堆栈空间,但更好的选择可能是减少已有的线程数

堆外内存根据定义是非托管的,因此不容易进行“调优”。甚至调整堆也不简单

64位JVM上的默认堆栈大小为1024K,因此700个线程将使用700 MB的虚拟内存

您不应该将虚拟内存大小与驻留内存大小混淆。64位应用程序上的虚拟内存几乎是可用的
    BufferedReader br = new BufferedReader(new FileReader("C:/dev/gistfile1.txt"));
    long total = 0;
    for(String line; (line = br.readLine())!= null;) {
        String[] parts = line.split("[- ]");
        long start = new BigInteger(parts[0], 16).longValue();
        long end = new BigInteger(parts[1], 16).longValue();
        long size = end - start + 1;
        if (size > 1000000)
            System.out.printf("%,d : %s%n", size, line);
        total += size;
    }
    System.out.println("total: " + total/1024);
7f0cffddf000-7f0cffedd000 rw-p 00000000 00:00 0 
7f0cffedd000-7f0cffee0000 ---p 00000000 00:00 0