当前位置: 首页 > news >正文

承德公司做网站/搜索点击软件

承德公司做网站,搜索点击软件,网站做优化有几种方式,网站建设如何去找客户说到 Java 很多人脑海会直接蹦出内存自动回收,会经常听到 GC 这些词,GC 指的是 Garbage Collection 也就是垃圾回收。说到垃圾回收就不可避免的去看下 Java 的内存管理机制。内存管理提到内存管理可能很多人都会联想起 C/C 的手动内存管理,以…

说到 Java 很多人脑海会直接蹦出内存自动回收,会经常听到 GC 这些词,GC 指的是 Garbage Collection 也就是垃圾回收。说到垃圾回收就不可避免的去看下 Java 的内存管理机制。

内存管理

提到内存管理可能很多人都会联想起 C/C++ 的手动内存管理,以及 Java/Python 的自动管理,但实际上这都是指的堆内存管理。常规的内存管理可以分成两个部分,栈内存管理和堆内存管理。

栈的发明解决了部分内存的自动回收,但是栈的局限在于只能自动管理固定长度的内存,而对于堆内存,不同语言有不同的管理方式:

纯手动管理 C/C++

自动管理 Java/Python/PHP/C# 等

半自动 C++ 智能指针 Swift/Rust 等

什么是 GC 以及为何要有 GC

对于通常含义上的 GC 可以参考维基词条, John McCarthy 在发明 Lisp 时一并发明了内存自动管理机制。

什么是内存垃圾,也就是程序在执行过程中再无法访问的对象,这些对象所占用的内存空间可以收回来重新使用。

优点:

编码容易

减少因内存管理而导致的 bug,野指针,内存泄露等等

GC 的缺点:

需要消耗额外的 CPU / Memory 资源

代码执行时间无法估计

GC 实现方式

Reference counting

引用计数,最简单也最容易实现的一种,原理是在每个对象中保存该对象的引用计数,当引用发生增减时对计数进行更改。

优点:

当对象不再被引用立即就会被释放,算法运行快

空间释放是针对个别执行,和其他算法相比,GC 中断时间比较短

问题:

额外的内存占用,每个对象需要一个 counter

引用发生增减时需要对计数做出正确的增减,如果发生计数错误可能会导致难以发现的内存错误

循环引用,两个对象互相引用,能解决但需要大量计算

引用计数不适合并行处理,多线程同时对引用计数进行增减时,引用计数可能会产生不一致的问题,而如果采用加锁方式,带来的开销也非常大

引用计数的例子:

Python

PHP

Swift/ OC

Mark and Sweep

标记清除,是最早开发出来的算法(1960 年),原理,从根开始可能被引用的对象用递归的方式进行标记,然后将没有标记的对象作为垃圾回收。

缺点:

在分配了大量对象,而只有一小部分存活的情况下,算法消耗的时间多

执行时间不可控

Copy and Collection

复制收集,为了克服标记清除的问题,在算法中将根开始被引用的对象复制到另外的空间中,然后将复制的对象所能够引用的对象用递归方式复制下去。

复制收集方式的过程相当于标记清除算法中的标记阶段,但由于清除阶段依然要对所有对象进行扫描,如果存在大量对象,而且大量对象已经死亡的情况,开销会加大。

优点:

没有内存碎片

复制收集过程中,按照对象被引用的顺序将对象复制到新空间,关系较近的对象被放到较近空间的可能性提高,局部性能提升,内存缓存可能更容易命中

缺点:

和标记清除相比,复制对象的开销加大,当存活对象较多的情况下,性能损耗

JVM 如何实现 GC

现代版的 GC 使用分代收集,按照对象存活时间长短来使用不同的垃圾回收算法。

heap 分为:

Young Generation: 新创建的对象,Young Generation 又被分成 Eden space(所有新对象开始的地方),两个 Survivor spaces(在存活一个 gc 之后移动到这里),当对象在 Young Generation 被回收,这是 minor garbage collection event

Old Generation: 当对象存活足够长时间,会从 Young Generation 移动到 Old Generation。当对象在 Old Generation 被回收,这是一次 major garbage collection event.

Permanent Generation: 类,方法等 Metadata 会保存在 Permanent Generation。不再被使用的 Classes (ClassLoader 回收后)会被回收。

所以一个对象在不同分区的流程可能是:

新对象在 Eden 中创建

Eden 满时进入 Survivor spaces

两个 Survivor 空间的对象相互交换

在 Survivor 存活一定时间后进入 Old

一种 JVM 的实现,由 1999 年引入,HotSpot 为代表,HotSpot JVM 有四种 Garbage Collector:

Serial GC : 所有的 garbage collection events 通过一个线程连续管理, Compaction 在每一次 garbage collection 之后执行

Parallel GC : 并行进行 minor garbage collection,一个线程用来 major garbage collection 和 Old Generation compaction

Concurrent-Mark-and-Sweep GC : 简称 CMS,多个线程用来 minor garbage collection ,使用和 Parallel 相同的算法。CMS 在应用程序之外运行,GC 和 应用程序并行,减少中断。不会执行 compaction

G1 GC(1.7+) : Garbage First,新的 garbage collector,用来替换 CMS,同样是并行并发的,但是原理和工作方式完全不一样

Java 的 GC 是不确定的,没有方法来预测何时会发生 gc。在代码中可以使用 System.gc() 或者 Runtime.gc() 方法来暗示 gc,但是 Java 不能保证 gc 一定会执行。

GC 的调优可以从 JVM 的参数调节:

-Xms 初始堆大小,可以设置和 Xmx 相同,避免每次垃圾回收后 JVM 重新分配内存

-Xmx 最大堆大小

-XX:NewRatio=n Young 和 old 区的大小比 1:n

-XX:MaxPermSize Permanent 大小

-XX:+UseG1GC 使用 G1

-XX:MaxGCPauseMillis=n 最大希望暂停时间

-XX:InitiatingHeapOccupancyPercent=n 堆使用到多少百分比时开始 CMS 过程

-XX:+PrintGC 输出 GC 日志

-XX:+PrintGCDetails 输出 GC 的详细日志

-XX:+PrintGCTimeStamps 输出 GC 时间戳

-XX:+PrintGCDateStamps 输出 GC 时间戳(日期形式,2019-01-01T01:01:02.212+0800)

-XX:+PrintHeapAtGC 进行 GC 的前后打印堆信息

-verbose:gc

-XX:+PrintReferenceGC 年轻代各个引用的数量以及时长

-Xloggc:../logs/gc.log 日志文件输出路径

JVM 内存区域划分

Heap 区

Eden

Survivor

Old gen

非 Heap 区:

Code Cache, 代码缓存区,它主要用于存放 JIT 所编译的代码

Perm Gen,Permanent Generation space,是指内存的永久保存区域

Jvm Stack

Local Method Stack

为什么需要 Survivor 区

前提知识,新生代内存中除了 Eden 区外还有两个 Survivor 区,Eden 占 80%,两块 Survivor 区占比 20%。

如果没有 Survivor ,Eden 区每进行一次 Minor GC,存活的对象都会被送到老年区,老年代很快被填满。

每进行一次 Minor GC,存活下来的对象会被计数 +1,当对象在 Minor GC 下存活多次,达到一个阈值后会被移动到老年代。

Survivor 存在的意义,减少被送到老年代的对象,减少 Full GC 发生,只有经历 16 次 Minor GC 还能在新生代中存活的对象,才会被送到老年代。

JVM 参数设置和调优

生产环境 Xms 和 Xmx 设置相同的值

In a production environment, if you monitor the GC data, you will notice that is a relatively short period of time (usually less than an hour), the JVM will eventually increase the heap size to the -Xmx setting. Each time the JVM increases the heap size it must ask the OS for additional memory, which takes time (and thus adds to the response time of any requests that were is process when the GC hit). And usually the JVM will never let go of that memeory. Therefore, since the JVM will eventually grab the -Xmx memory, you might as well set it to that at the beginning.

Another point is that with a smaller heap size (starting with -Xms), GCs will happen more often. So by starting with a larger heap initially the GCs will happen not as often.

Finally, in a production environment, you usually run only one app server per OS (or per VM). So since the app server is not competing for memory with other apps you might as well give it the memory up front.

Note that the above is for production. It applies also to the syatem test environment since the system test environment should mimic production as close as possible.

For development, make -Xms and -Xmx different. Usually, you are not doing much work with the app server in development, so it will often stay with the -Xms heap setting. Also, since in development the app server will share the machine with lots of other apps (mail client, word processors, IDEs, databases, browsers, etc), setting the -Xms to a smaller size lets the app server play more nicely with the other software that is also competing for the same resources.

gc log

enable gc log

通过如下任意一个开启 gc log:

-XX:+PrintGC

-XX:+PrintGCDetails

-Xloggc:gc.log

开启 -XX:+PrintGC 后,打印日志:

[GC (Allocation Failure) 61905K->9848K(256000K), 0.0040139 secs]

说明:

GC 表示是一次 YGC(Young GC)

Allocation Failure 表示是失败

61905KK->9848K 表示年轻代从 61905KK 降为 9848K

256000K 表示整个堆的大小

0.0040139 secs 表示这次 GC 总计所用的时间

开启 -XX:+PrintGCDetails 后,日志:

2020-03-28T08:55:24.916+0800: 229805.169: [GC (Allocation Failure) 2020-03-28T08:55:24.916+0800: 229805.170: [ParNew: 584336K->24291K(629120K), 0.0145141 secs] 1849190K->1289986K(2027264K), 0.0155393 secs] [Times: user=0.08 sys=0.02, real=0.02 secs]

说明:

第一个时间戳 2020-03-28T08:55:24.916+0800 是 Mirror GC 发生的时间

229805.169 GC 开始的时间,这里是相对 JVM 启动时间,单位秒

GC 用来区分 GC 类型,Minor GC 或者 Full GC

Allocation Failure 分配内存失败

ParNew 收集器名称

584336K->24291K 前后年轻代使用

629120K 整个年轻代的容量

跟随的时间是 gc 发生的时间

1849190K->1289986K 堆前后使用情况

后接的时间是 ParNew 收集器标记和复制年轻代存活的对象的时间

最后出现的 [Times] 中三个时间是:

user: GC 线程在垃圾收集中使用 CPU 时间

sys: 系统调用时间

real: 应用被暂停的时钟时间,GC 是多线程的所以, real < (user + sys)

Example

public class GCLogDemo {

public static void main(String[] args) {

int _1m = 1024 * 1024;

byte[] data = new byte[_1m];

// 将 data 置为 null 即让它成为垃圾

data = null;

// 通知垃圾回收器回收垃圾

System.gc();

}

}

相关命令

jstat

jstat 可以用来查看 JVM 数据信息:

jstat [options] vmid [interval] [count]

options 使用 -gc 或者 -gcutil

这里的 vmid 是 vm 的进程号,当前运行的 java 进程号

比如查看 gc 情况

jstat -gc [PID]

每 5 秒打印一次特定 PID 的 GC 情况

jstat -gc [PID] 5000

jstat -gc [PID] 5s

结果说明:

前提知识,新生代内存中除了 Eden 区外还有两个 Survivor 区,Eden 占 80%,两块 Survivor 区占比 20%。

S0C:当前年轻代中第一个 survivor(幸存区)的容量 (字节) ,简记成 Survivor 0 Current

S1C:当前年轻代中第二个 survivor(幸存区)的容量 (字节)

S0U:年轻代中第一个 survivor(幸存区)目前已使用空间 (字节)

S1U:年轻代中第二个 survivor(幸存区)目前已使用空间 (字节)

EC:当前年轻代中 Eden(伊甸园)的容量 (字节)

EU:年轻代中 Eden(伊甸园)目前已使用空间 (字节)

OC:当前 Old 代的容量 (字节)

OU:Old 代目前已使用空间 (字节)

PC:当前 Perm(持久代)的容量 (字节)

PU:Perm(持久代)目前已使用空间 (字节)

YGC:从应用程序启动到采样时年轻代中 gc 次数

YGCT:从应用程序启动到采样时年轻代中 gc 所用时间 (s)

FGC:从应用程序启动到采样时 old 代(全 gc)gc 次数

FGCT:从应用程序启动到采样时 old 代(全 gc)gc 所用时间 (s)

GCT:从应用程序启动到采样时 gc 用的总时间 (s)

NGCMN:年轻代 (young) 中初始化(最小)的大小 (字节)

NGCMX:年轻代 (young) 的最大容量 (字节)

NGC:年轻代 (young) 中当前的容量 (字节)

OGCMN:old 代中初始化(最小)的大小 (字节)

OGCMX:old 代的最大容量 (字节)

OGC:old 代当前新生成的容量 (字节)

PGCMN:perm 代中初始化(最小)的大小 (字节)

PGCMX:perm 代的最大容量 (字节)

PGC:perm 代当前新生成的容量 (字节)

S0:年轻代中第一个 survivor(幸存区)已使用的占当前容量百分比

S1:年轻代中第二个 survivor(幸存区)已使用的占当前容量百分比

E:年轻代中 Eden(伊甸园)已使用的占当前容量百分比

O:old 代已使用的占当前容量百分比

P:perm 代已使用的占当前容量百分比

S0CMX:年轻代中第一个 survivor(幸存区)的最大容量 (字节)

S1CMX :年轻代中第二个 survivor(幸存区)的最大容量 (字节)

ECMX:年轻代中 Eden(伊甸园)的最大容量 (字节)

DSS:当前需要 survivor(幸存区)的容量 (字节)(Eden 区已满)

TT: 持有次数限制

MTT : 最大持有次数限制

如果使用 -gcutil 则是打印 GC 的使用率:

jstat -gcutil -h 10 [PID] 1000

jmap

使用 jmap 打印堆相关信息,更多细节可以参考这篇文章

jhat

更多关于 jhat 的用法可以参考这篇

reference

http://www.jmfq.cn/news/5109931.html

相关文章:

  • 做宣传单用什么网站/电商平台怎么注册
  • 服务器如何做网站/长春百度推广排名优化
  • 企业网站营销案例/网站推广优化
  • 做网站还是小程序/整合营销名词解释
  • 香港网站域名是什么结尾/营销平台
  • 企业网站建设的可行性/百度投放平台
  • 不想花钱做网站推广/如何推广一个平台
  • 网站建设阿里云/有哪些免费网站可以发布广告
  • 网站建设要用H5吗/宁德市中医院
  • 公司网站建设注意事项/哪里有专业的培训机构
  • 我想建立一个网站不知道怎么做啊/免费广告推广软件
  • 一级a做爰片阿v祥仔网站/泰安百度公司代理商
  • 我的世界做rpg网站/怎样推广自己的app
  • 连云港网站建设公司/拉新app推广平台
  • 做美女图片网站挣钱么/五年级下册数学优化设计答案
  • 合优网站建设/子域名大全查询
  • 做淘客网站用备案吗/如何注册一个网站
  • 建设网站的具体步骤/友情链接交换群
  • 湖南省城乡与住房建设厅网站/seo优化点击软件
  • 坑梓网站建设咨询/百度官方免费下载
  • 如何做适合手机访问的网站/网络广告人社区官网
  • 哈尔滨制作网站多少钱/常州seo第一人
  • 柳林网站建设/关键词优化快排
  • 赣州网站优化制作/网店推广策划方案
  • 企业建设网站个人总结报告/线上营销培训
  • 湖南长沙网站建设公司电话/企业培训计划
  • 社区网站优化/网络推广平台收费不便宜
  • 行业网站推广怎么做/seo的基本步骤顺序正确的是
  • 哪里有网站可以做动态视频倒计时/高级搜索引擎技巧
  • 找晚上做的工作去哪个网站/现在最火的推广平台