在高性能硬件上部署程序,目前主要有两种方式:

  • 通过 64 位 JDK 来使用大内存;
  • 使用若干个 32 位虚拟机建立逻辑集群来利用硬件资源。

使用 64 位 JDK 管理大内存

堆内存变大后,虽然垃圾收集的频率减少了,但每次垃圾回收的时间变长。 如果堆内存为14 G,那么每次 Full GC 将长达数十秒。如果 Full GC 频繁发生,那么对于一个网站来说是无法忍受的。

对于用户交互性强、对停顿时间敏感的系统,可以给 Java 虚拟机分配超大堆的前提是有把握把应用程序的 Full GC 频率控制得足够低,至少要低到不会影响用户使用。

可能面临的问题:

  • 内存回收导致的长时间停顿;
  • 现阶段,64位 JDK 的性能普遍比 32 位 JDK 低;
  • 需要保证程序足够稳定,因为这种应用要是产生堆溢出几乎就无法产生堆转储快照(因为要产生超过 10GB 的 Dump 文件),哪怕产生了快照也几乎无法进行分析;
  • 相同程序在 64 位 JDK 消耗的内存一般比 32 位 JDK 大,这是由于指针膨胀,以及数据类型对齐补白等因素导致的。

使用 32 位 JVM 建立逻辑集群

在一台物理机器上启动多个应用服务器进程,每个服务器进程分配不同端口, 然后在前端搭建一个负载均衡器,以反向代理的方式来分配访问请求。

考虑到在一台物理机器上建立逻辑集群的目的仅仅是为了尽可能利用硬件资源,并不需要关心状态保留、热转移之类的高可用性能需求, 也不需要保证每个虚拟机进程有绝对的均衡负载,因此使用无 Session 复制的亲合式集群是一个不错的选择。 我们仅仅需要保障集群具备亲合性,也就是均衡器按一定的规则算法(一般根据 SessionID 分配) 将一个固定的用户请求永远分配到固定的一个集群节点进行处理即可。

可能遇到的问题:

  • 尽量避免节点竞争全局资源,如磁盘竞争,各个节点如果同时访问某个磁盘文件的话,很可能导致 IO 异常;
  • 很难高效利用资源池,如连接池,一般都是在节点建立自己独立的连接池,这样有可能导致一些节点池满了而另外一些节点仍有较多空余;
  • 各个节点受到 32 位的内存限制;
  • 大量使用本地缓存的应用,在逻辑集群中会造成较大的内存浪费,因为每个逻辑节点都有一份缓存,这时候可以考虑把本地缓存改成集中式缓存。

调优案例分析与实战

场景描述

一个小型系统,使用 32 位 JDK,4G 内存,测试期间发现服务端不定时抛出内存溢出异常。 加入 -XX:+HeapDumpOnOutOfMemoryError(添加这个参数后,堆内存溢出时就会输出异常日志), 但再次发生内存溢出时,没有生成相关异常日志。

分析

在 32 位 JDK 上,1.6G 分配给堆,还有一部分分配给 JVM 的其他内存,直接内存最大也只能在剩余的 0.4G 空间中分出一部分, 如果使用了 NIO,JVM 会在 JVM 内存之外分配内存空间,那么就要小心“直接内存”不足时发生内存溢出异常了。

直接内存的回收过程

直接内存虽然不是 JVM 内存空间,但它的垃圾回收也由 JVM 负责。

垃圾收集进行时,虚拟机虽然会对直接内存进行回收, 但是直接内存却不能像新生代、老年代那样,发现空间不足了就通知收集器进行垃圾回收, 它只能等老年代满了后 Full GC,然后“顺便”帮它清理掉内存的废弃对象。 否则只能一直等到抛出内存溢出异常时,先 catch 掉,再在 catch 块里大喊 “System.gc()”。 要是虚拟机还是不听,那就只能眼睁睁看着堆中还有许多空闲内存,自己却不得不抛出内存溢出异常了。

JVM学习十一 - (复习)性能调优的更多相关文章

  1. JVM内存模型与性能调优

    堆内存(Heap) 堆是由Java虚拟机(JVM,下文提到的JVM特指Sun hotspot JVM)用来存放Java类.对象和静态成员的内存空间,Java程序中创建的所有对象都在堆中分配空间,堆只用 ...

  2. JVM常用命令和性能调优建议 [Could not create the Java virtual machine]

    一.查看jvm常用命令jinfo:可以输出并修改运行时的java 进程的opts. jps:与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程号. ...

  3. JVM常用命令和性能调优建议

      一.查看jvm常用命令jinfo:可以输出并修改运行时的java 进程的opts. jps:与unix上的ps类似,用来显示本地的java进程,可以查看本地运行着几个java程序,并显示他们的进程 ...

  4. 艾编程coding老师:深入JVM底层原理与性能调优

    1. Java内存模型JMM,内存泄漏及解决方法:2. JVM内存划分:New.Tenured.Perm:3. 垃圾回收算法:Serial算法.并行算法.并发算法:4. JVM性能调优,CPU负载不足 ...

  5. jvm参数设置和性能调优

    1.Java虚拟机运行时的数据区 2.常用的内存区域调节参数 -Xms:初始堆大小,默认为物理内存的1/64(<1GB):默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40% ...

  6. jvm系列(五):tomcat性能调优和性能监控(visualvm)

    tomcat服务器优化 1.JDK内存优化 根据服务器物理内容情况配置相关参数优化tomcat性能.当应用程序需要的内存超出堆的最大值时虚拟机就会提示内存溢出,并且导致应用服务崩溃.因此一般建议堆的最 ...

  7. JVM性能调优

    摘自:http://uule.iteye.com/blog/2114697 JVM垃圾回收与性能调优总结 JVM调优的几种策略 一.JVM内存模型及垃圾收集算法  1.根据Java虚拟机规范,JVM将 ...

  8. 【十一】jvm 性能调优工具之 jmap

    jvm 性能调优工具之 jmap 概述 命令jmap是一个多功能的命令.它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息.查看 ClassLoader 的信息以及 fi ...

  9. 2020年薪30W的Java程序员都要求熟悉JVM与性能调优!

    前言 作为Java程序员,你有没有被JVM伤害过?面试的时候是否碰到过对JVM的灵魂拷问?   一.JVM 内存区域划分 1.程序计数器(线程私有) 程序计数器(Program Counter Reg ...

  10. Tomcat性能调优-JVM监控与调优

    参数设置 在Java虚拟机的参数中,有3种表示方法用"ps -ef |grep "java"命令,可以得到当前Java进程的所有启动参数和配置参数: 标准参数(-),所有 ...

随机推荐

  1. CS5213设计HDMI转VGA带音频方案+设计电路|直接替代AG6200 AG6201

    台湾安格AG6200 AG6201专门用于设计HDMI转VGA带音频输出的方案芯片,CS5213是一款HDMI to VGA转换器且结合了HDMI输入接口和模拟RGB DAC输出.带支持片上音频数模转 ...

  2. playwright--自动化(三): 跳过检测 使用正常谷歌 指定用户数据 下载文件

    首先上一个被拷贝的惨不忍睹 上一个是滑块验证[https://www.cnblogs.com/carl-/p/15761861.html] 还是前两天做一个商城后台爬虫,限制用户缓存,不能用谷歌开发版 ...

  3. SpringBoot集成Actuator健康指示器health

    1.说明 本文详细介绍Actuator提供的HealthIndicators, 即健康指示器的配置使用, 利用自动配置的健康指标, 检查正在运行的应用程序的状态, 以及自定义健康指标的方法. 监控软件 ...

  4. Ubuntu安装Jenkins是报错:The following signatures couldn't be verified because the public key is not available: NO_PUBKEY XXXXXXXXXXX

    我使用Ubuntu16.04安装Jenkins时,按照官网的要求,步骤如下(https://pkg.jenkins.io/debian-stable/): # 添加Key sudo wget -q - ...

  5. MongoDB高级应用之高可用方案实战(4)

    1.MongDB启动与关闭 1.1.命令行启动 ./mongod --fork --dbpath=/opt/mongodb/data ----logpath=/opt/mongodb/log/mong ...

  6. CSS基础 CSS的三大特性以及选择器优先级计算方法

    1.子元素默认会继承父元素的样式,但不是所有的元素都有继承 常见的继承父元素特点的元素有: 1.color 2.font-sytle.font-weight.font-size.font-family ...

  7. 为EasySharding.EFCore提供Dapper相关查询扩展

    承接上一篇博文中的中间件基本都是写入性的操作,但对于查询操作实际上是比较鸡肋的,如果单纯的查询,没有分表的情况下基本还能适应,这里为了Dapper提供了扩展 Dapper的扩展查询是需要写表名称的,所 ...

  8. cnetos7安装字体

    1 先下载字体 链接:https://pan.baidu.com/s/1FEV7K8c8S6o3gBukkSGp4w 提取码:font 2 安装字体脚本 vi font.sh #!/bin/bash ...

  9. MySQL删除数据库或表(DROP DATABASE/table语句)

    DROP DATABASE [ IF EXISTS ] <数据库名> DROP table[ IF EXISTS ] <数据库表名> 语法说明如下: <数据库名>: ...

  10. Collection中的常用方法

    1:往集合中添加元素 boolean add(Object o);2:获取集合中元素的个数 int size();3:boolean contains(Object o) 判断集合是否包含元素o4:清 ...