文档章节

JVM基础之java内存管理以及GC

chape
 chape
发布于 2013/12/25 00:08
字数 5569
阅读 296
收藏 22
点赞 0
评论 0

内存管理简介 

内存管理的职责为分配内存,回收内存。 
没有自动内存管理的语言/平台容易发生错误。 
典型的问题包括悬挂指针问题,一个指针引用了一个已经被回收的内存地址,导致程序的运行完全不可知。 
另一个典型问题为内存泄露,内存已经分配,但是已经没有了指向该内存的指针,导致内存泄露。 
程序员要花费大量时间在调试该类问题上。 

GC简介 

因此引入了Garbage Collector机制,由运行时环境来自动管理内存。 
Garbage Collector解决了悬挂指针和内存泄露大部分的问题(不是全部)。 
注意Garbage Collector(简称Collector)和Garbage Collection(简称GC)的区别。 

Collector的职责: 
分配内存。 
保证有引用的内存不被释放。 
回收没有指针引用的内存。 


对象被引用称为活对象,对象没有被引用称为垃圾对象/垃圾/垃圾内存,找到垃圾对象并回收是Collector的一个主要工作,该过程称为GC。 
Collector一般使用一个称为堆的内存池来进行内存的分配和回收。 
一般的,当堆内存满或者达到一个阀值时,堆内存或者部分堆内存被GC。 

好的Collector的特性 

保证有引用的对象不被GC。 
快速的回收内存垃圾。 
在程序运行期间GC要高效,尽量少的影响程序运行。和大部分的计算机问题一样,这是一个关于空间,时间,效率平衡的问题。 
避免内存碎片,内存碎片导致占用大量内存的大对象内存申请难以满足。可以采用Compaction技术避免内存碎片。Compaction技术:把活对象移向连续内存区的一端,回收其余的内存以便以后的分配。 
良好的扩展性,内存分配和GC在多核机器上不应该成为性能瓶颈。 

设计或选择Collector 

串行或并行。 
串行Collector在多核上也只有一个线程在运行,并行Collector可以同时有多个线程执行GC,但是其算法更复杂。 
并发或Stop the World。 
Stop the World Collection执行GC时,需要冻住所有内存,因此更简单一些,但是,在GC时,程序是被挂起的。并发GC时,程序和GC同时执行,当然,一般的并发GC算法还是需要一些Stop the World时间。 
Compacting or Non-compacting or Copying 
Compacting: 去除内存碎片,回收内存慢,分配内存快。 
Non-compacting: 容易产生内存碎片,回收内存快,分配内存慢,对大对象内存分配支持不好。 
Copying: 复制活对象到新的内存区域,原有内存直接回收,需要额外的时间来做复制,额外的空间来做存储。 

GC性能指标 

Throughput: 程序时间(不包含GC时间)/总时间。 
GC overhead: GC时间/总时间。 
Pause time: GC运行时程序挂起时间。 
Frequency of GC: GC频率。 
Footprint: a measure of size, such as heap size。 
Promptness:对象变为垃圾到该垃圾被回收后内存可用的时间。 

GC

依赖于不同的场景,对于GC的性能指标的关注点也不一样。 

堆内存GC

JVM(采用分代回收的策略),用较高的频率对年轻的对象(young generation)进行YGC,而对老对象(tenured generation)较少(tenured generation 满了后才进行)进行Full GC。这样就不需要每次GC都将内存中所有对象都检查一遍。

非堆内存不GC

GC不会在主程序运行期对PermGen Space进行清理,所以如果你的应用中有很多CLASS(特别是动态生成类(如反射),当然permgen space存放的内容不仅限于类)的话,就很可能出现PermGen Space错误。

内存申请、对象衰老过程

一、内存申请过程

•JVM会试图为相关Java对象在Eden中初始化一块内存区域;

•当Eden空间足够时,内存申请结束。否则到下一步;

•JVM试图释放在Eden中所有不活跃的对象(minor collection),释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区;

•Survivor区被用来作为Eden及old的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区;

•当old区空间不够时,JVM会在old区进行major collection

•完全垃圾收集后,若Survivor及old区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现"Out of memory错误";

二、对象衰老过程

•新创建的对象的内存都分配自eden。Minor collection的过程就是将eden和在用survivor space中的活对象copy到空闲survivor space中。对象在young generation里经历了一定次数(可以通过参数配置)的minor collection后,就会被移到old generation中,称为tenuring。

•GC触发条件

 

GC类型 触发条件 触发时发生了什么 注意 查看方式
YGC eden空间不足

清空Eden+from survivor中所有no ref的对象占用的内存
将eden+from sur中所有存活的对象copy到to sur中
一些对象将晋升到old中:
to sur放不下的
存活次数超过turning threshold中的
重新计算tenuring threshold(serial parallel GC会触发此项)

重新调整Eden 和from的大小(parallel GC会触发此项)

全过程暂停应用
是否为上海止回阀多线程处理由具体的GC决定
jstat –gcutil 
gc log
FGC

old空间不足
perm空间不足
显示调用System.GC, RMI等的定时触发
YGC时的悲观策略
dump live的内存信息时(jmap –dump:live)

清空heap中no ref的对象
permgen中已经被卸载的classloader中加载的class信息

如配置了CollectGenOFirst,则先触发YGC(针对serial GC)
如配置了ScavengeBeforeFullGC,则先触发YGC(针对serial GC)

 
全过程暂停应用
是否为多线程处理由具体的GC决定

是否压缩需要看配置的具体GC
jstat –gcutil 
gc log

permanent generation空间不足会引发Full GC,仍然不够会引发PermGen Space错误。

分代GC 

      分代GC把内存划分为多个代(内存区域),每个代存储不同年龄的对象。 常见的分为2代,young和old。 
分配内存时,先从young代分配,如果young代已满,可以执行GC(可能导致对象提升),如果有空间,则分配,如果young代还是没有空间,可以对整个内存堆GC。 
young代GC后还存活的对象可以提升到old代。 
该机制基于以下观察事实: 
1 大部分新分配的对象很快就没有引用了,变成垃圾。 
2 很少有old代对象引用young代对象。 
基于代内存存储对象的特性,对不同代的内存可以使用不同的GC算法。 
Young代GC需要高效,快速,频繁的执行,关注点主要在速度上。 
Old代由于增长缓慢,因此GC不频繁,但是其内存空间比较大,因此,需要更长时间才能执行完GC。关注点在内存空间利用率上。 
 

Java Collector 

Jvm的内存分为3代。Young, Old, Permanent。 
大部分对象存储在Young代。 
在Young代中经历数次GC存活的对象可以提升到Old代,大对象也可以直接分配到Old代。 
Permanent代保存虚拟机自己的静态(refective)数据,例如类(class)和方法(method)对象。 
Young代由一个Eden和2个survivor组成。大部分的对象的内存分配和回收在这里完成。 

Survivor存储至少经过一次GC存活下来的对象,以增大该对象在提升至old代前被回收的机会。2个survivor中有一个为空。分别为From和to survivor。 

当young代内存满,执行young代GC(minor GC)。 
当old或permanent代内存满,执行full GC(major GC),所有代都被GC。一般先执行young GC,再执行old, permanent GC。 
有时old代太满,以至于如果young GC先运行,则无法存储提升的对象。这时,Young GC不运行,old GC算法在整个堆上运行(CMS collector是个例外,该collector不能运行在young 代上)。 

 


快速内存分配 


大部分的内存分配请求发生时,Collector都有一块大的连续内存块,简单的内存大小计算和指针移动就可以分配内存了。因此非常快速。该技术称为bump –the-pointer技术。 

对于多线程的内存分配,每个线程使用Thread Local Allocation Buffer(TLAB)进行分配,因此还是很高效。TLAB可以看作一个线程的特殊代。只有TLAB满的时候才需要进行同步操作。 

GC根集合 


GC运行时当前程序可以直接访问的对象。如线程中当前调用栈的方法参数,局部变量,静态变量,当前线程对象等等。 
Collector根据GC根集合来寻找所有活对象。GC根集合不可达对象自然就是垃圾了。 

Serial Collector 


单线程,Young and old GC是串行,stop the world GC的。 
Young GC。 
Eden中活对象copy到to survivor中,大对象直接进old代。 
From survivor中相对老的活对象进入old代,相对年轻的对象进入to survivor中。 
如果to survivor放不下活对象,则这些活对象直接进入old。 
经历过young GC,Eden和from survivor都变成空的内存区域,to survivor存储有活的对象。To survivor和from survivor角色互换。 

Old permanent GC。 
Mark-sweep-compact算法。 
S1 标识哪些对象是活的对象。 
S2 标识哪些对象是垃圾。 
S3 把活的对象压缩到内存的一端,以便可以使用bump –the-pointer处理以后的内存分配请求。 

非server-class machine 的默认GC。 
也可以使用命令行参数来设定。 
-XX:+UseSerialGC 


Parallel Collector/Throughput Collector 


利用了现代计算机大部分都是多核的事实。 
Young GC。 
和Serial Collector一样,是一个stop the world和copying Collector。只不过是多线程并行扫描和做copy,提高速度,减少了stop the world的时间,增大了throughput。 
Old permanent GC。 
和serial collector一样。Mark-sweep-compact算法。单线程。 

Server-class machine的默认GC。 
也可以使用命令行参数来设定。 
-XX:+UseParallelGC 


Parallel Compacting Collector 


Young GC。 
和Parallel Collector一样。 
Old Permanent GC。 
Stop the world,并且多线程并发GC。 
每一代被划分为一些长度固定的区域。 
第1步(mark phase),GC根集合划分后分发给多个GC线程,每个GC线程更新可达活对象所在区域的信息(活对象的内存位置,大小)。 
第2步(summary phase),操作在区域上,而不是对象上。由于以前GC的影响,内存的一端活对象的密度比较高,在该阶段找到一个临界点,该临界点以前的区域由于活对象内存密度高,不参与GC,不做compact。该临界点之后的区域参与GC,做compact。该阶段为单线程执行。 
第3步(compact phase)。GC多线程使用summary info做回收和compact工作。 

可以设置GC线程数,防止GC线程长时间占有整台机器的资源。 
-XX:ParallelGCThreads=n 
使用命令行参数来设定。 
-XX:+UseParallelOldGC 


Concurrent Mark Sweep Collector (CMS)
 


Young GC。 
和Parallel Collector一样。 
Old permanent GC。 
GC和程序并发执行。 
Initial Phase:短暂停,标记GC根集合。单线程执行。 
Concurrent marking phase: GC多线程标记从根集合可达的所有活对象。程序和GC并发运行。由于是并发运行,有可能有活对象没有被标记上。 
concurrent pre-clean:单线程,并发执行。 
Remark phase: 短暂停,多线程标记在Concurrent marking phase中有变化的相关对象。 
Concurrent sweep phase:和程序并发执行。单线程执行。不做compacting。 
concurrent reset:单线程,并发执行。 

CMS不做compacting,不能使用bump-the-pointer技术,只能使用传统的内存空闲链表技术。 
导致内存分配变慢,影响了Young代的GC速度,因为Young的GC如果有对象提升的话依赖于Old的内存分配。 
CMS需要更多的内存空间,因为mark phase时程序还是在运行,程序可以申请更多的old空间。在mark phase中,CMS保证标识活对象,但是该过程中,活对象可能转变为垃圾,只能等待下一次GC才能回收。 

和其他Collector不同,CMS不是等到old满时才GC,基于以前的统计数据(GC时间,Old空间消耗速度)来决定何时GC。CMS GC也可以基于old空间的占用率。 
命令行参数: 
-XX:CMSInitiatingOccupancyFraction=n,n为百分比,默认68。 
可以设置 
-XX:+UseCMSInitiatingOccupancyOnly 来使vm只使用old内存占用比来触发CMS GC。 

Incremental Mode。 
CMS的concurrent phase可以是渐进式执行。以减少程序的一次暂停时间。 

命令行参数: 
-XX:+UseConcMarkSweepGC 
-XX:+CMSIncrementalMode 


4种Collector的对比和适用场景。

 
直到jdk1.3.1,java只提供Serial Collector,Serial Collector在多核的机器上表现比较差。主要是throughput比较差。 
大型应用(大内存,多核)应该选用并行Collector。 
Serial Collector:大多数client-style机器。对于低程序暂停时间没有需求的程序。 
Parallel Collector:多核机器,对于低程序暂停时间没有需求的程序。 
Parallel Compacting Collector:多核机器,对于低程序暂停时间有需求的程序。 
CMS Collector:和Parallel Compacting Collector相比,降低了程序暂停时间,但是young GC程序暂停时间变长,需要更大的堆空间,降低了程序的throughput。 


Ergonomics 


J2SE 5.0后,Collector的选择,堆大小的选择,VM(client还是server)的选择,都可以依赖平台和OS来做自动选择。 

JVM会自动选择使用server mode还是client mode。但是我们一样可以手工设置。 
java -server -client 

Server-class machine的选择: 
2个或更多的处理器  
And 
2G或更多的物理内存 
And 
不是32bits,windows OS。 

Client-class 
The client JVM 
The serial collector 
Initial heap size = 4M 
Max heap size=64M 

Server-class 
The server JVM 
The parallel collector 
Initial heap size= 1/64物理内存(>=32M),最大1G。 
Max heap size=1/4物理内存,最大1G。 


基于行为的调优。 

可以基于最大暂停时间或throughput。 

-XX:MaxGCPauseMillis=n 
指示vm调整堆大小和其他参数来满足这个时间需求。如果vm不满足该目标,则减小堆大小来满足该目标。该目标没有默认值。 

-XX:GCTimeRatio=n 
GC time/APP time=1/(1+n) 
如n=99表示GC时间占整个运行时间的1%。 
如果该目标不能满足,则增大堆大小来满足该目标。默认值n=99。 

Footprint Goal 
如果最大暂停时间和Throughput目标都满足了,则减少堆大小直到有一个目标不满足,然后又回调。 

目标优先级: 
最大暂停时间>Throughput>footprint。 


GC调优 


由于有了Ergonomics,第一个建议就是不要手工去配置各种参数。让系统自己去根据平台和OS来选择。然后观测性能,如果OK的话,呵呵,不用搞了。 

但是Ergonomics也不是万能的。因此还是需要程序员来手工搞。 
注意性能问题一定要测量/调优/测量/调优不停的循环下去。 

Vm mode 选择。 
Java -server server mode. 
Java -client client mode. 


观测性能主要使用gc的统计信息。 
-XX:+PrintGC 输出GC信息。 
-XX:+PrintGCDetails输出GC详细信息。 
-XX:+PrintGCTimeStamps 输出时间戳,和–XX:+PrintGC 或–XX:+PrintGCDetails一起使用。 
-Xloggc: gc.log 输出到指定文件。 


1 决定堆内存大小。 
决定整个堆内存的大小。内存的大小对于Collector的性能影响是最大的。 

使用以下参数来决定堆内存的大小。 
可以决定堆空间的起始值和最大值,大型程序可以考虑把起始值调大,避免程序启动时频繁GC和内存扩展申请。 
以及堆空间中可用内存的比例范围,vm会动态管理堆内存来满足该比例范围。 
-XX:MinHeapFreeRatio=n 
-XX:MaxHeapFreeRatio=n 
-Xmsn Young和Old的起始内存 
-Xmxn Young和Old的最大内存 

2 决定代空间大小。 
Young代空间越大,则minor GC的频率越小。但是,给定堆内存大小,Young代空间大,则major GC频率变大。 
如果没有过多的Full GC或者过长的暂停时间问题,给young代尽量大的空间。 

Young Generation Guarantee。 
对于serial collector,当执行minor GC时,必须保证old代中有可用的空间来处理最坏情况(即eden和survivor空间中的对象都是活对象,需要提升至old空间),如果不满足,则该minor GC触发major GC。所以对于serial collector,设置eden+survivor的内存不要大过old代内存。 
其他collector不做该保证,只有old代无法存储提升对象时才触发major GC。 

对于其他collector,由于多线程做minor GC时,考虑到最坏情况,每个线程要在old代内存预留一定空间做对象提升,因此可能导致内存碎片。因此old代内存应该调整的更大一些。 

-XX:NewSize=n young代空间下限。 
-XX:MaxNewSize=n young代空间上限。 
-XX:NewRatio=n young和old代的比例。 
-XX:SurvivorRatio=n Eden和单个survivor的比例。 

-XX:PermSize=n Permanent起始值。 
-XX:MaxPermSize=n Permanent最大值。 

3 决定使用Collector 
可以考虑是否需要换一个Collector。 
Collector选择 
-XX:+UseSerialGC Serial 
-XX:+UseParallelGC Parallel 
-XX:+UseParallelOldGC Parallel compacting 
-XX:+UseConcMarkSweepGC Concurrent mark–sweep (CMS) 

Parallel和Parallel Compacting Collector. 
-XX:ParallelGCThreads=n 
-XX:MaxGCPauseMillis=n 
-XX:GCTimeRatio=n 
设定目标好于明确设定参数值。 

为了增大Throughput,堆大小需要变大。可以把堆大小设为物理内存允许的最大值(同时程序不swapping)来检测该环境可以支持的最大throughput。 
为了减小最大暂停时间和footprint,堆大小需要变小。 
2个目标有一定的矛盾,因此要视具体应用场景,做平衡。 

CMS Collector 
-XX:+CMSIncrementalMode 和CMS同时使用。 
-XX:+CMSIncrementalPacing 和CMS同时使用。 
-XX:ParallelGCThreads=n 
-XX:CMSInitiatingOccupancyFraction=n,n为百分比,默认68。 


OutOfMemoryError 


可以指定 
-XX:+HeapDumpOnOutOfMemoryError 
当发生OutOfMemoryError时dump出堆内存。 

发生OutOfMemoryError时可以观测该Error的详细信息。 

Java heap space: 
调整堆大小。 
程序中含有大量带有finalize方法的对象。执行finalize方法的线程顶不住了。 
PermGen space: 
Permanent代内存不够用了。 
Requested array size exceeds VM limit。 
堆内存不够用。 
程序bug,一次分配太多内存。 

freeMemory(),totalMemory(),maxMemory() 
java.lang.Runtime类中的 freeMemory(), totalMemory(), maxMemory()这几个方法的反映的都是 java这个进程的内存情况,跟操作系统的内存根本没有关系。 

maxMemory()这个方法返回的是java虚拟机(这个进程)能构从操作系统那里挖到的最大的内存,以字节为单位,如果在运行java程序的时 候,没有添加-Xmx参数,那么就是jvm默认的可以使用内存大小,client为64M,server为1G。如果添加了-Xmx参数,将以这个参数后面的值为准。 

totalMemory()这个方法返回的是java虚拟机现在已经从操作系统那里挖过来的内存大小,也就是java虚拟机这个进程当时所占用的所有内存。如果在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操作系统那里挖的,基本上是用多少挖多少,直 到挖到maxMemory()为止,所以totalMemory()是慢慢增大的。如果用了-Xms参数,程序在启动的时候就会无条件的从操作系统中挖 -Xms后面定义的内存数,然后在这些内存用的差不多的时候,再去挖。 

freeMemory()是什么呢,刚才讲到如果在运行java的时候没有添加-Xms参数,那么,在java程序运行的过程的,内存总是慢慢的从操 作系统那里挖的,基本上是用多少挖多少,但是java虚拟机100%的情况下是会稍微多挖一点的,这些挖过来而又没有用上的内存,实际上就是 freeMemory(),所以freeMemory()的值一般情况下都是很小的,但是如果你在运行java程序的时候使用了-Xms,这个时候因为程 序在启动的时候就会无条件的从操作系统中挖-Xms后面定义的内存数,这个时候,挖过来的内存可能大部分没用上,所以这个时候freeMemory()可能会有些大。 


jmap工具的使用
 


jmap pid 查看共享对象。 
jmap -heap pid 查看java进程堆的相关信息。 

$ jmap -heap 5695  

Attaching to process ID 5695, please wait...  
Debugger attached successfully.  
Server compiler detected.  
JVM version is 17.0-b16  
using parallel threads in the new generation.  
using thread-local object allocation.  
Concurrent Mark-Sweep GC  
Heap Configuration:  
   MinHeapFreeRatio = 40  
   MaxHeapFreeRatio = 70  
   MaxHeapSize      = 1342177280 (1280.0MB)  
   NewSize          = 134217728 (128.0MB)  
   MaxNewSize       = 134217728 (128.0MB)  
   OldSize          = 4194304 (4.0MB)  
   NewRatio         = 2  
   SurvivorRatio    = 20000  
   PermSize         = 100663296 (96.0MB)  
   MaxPermSize      = 134217728 (128.0MB)  
Heap Usage:  
New Generation (Eden + 1 Survivor Space):  
   capacity = 134152192 (127.9375MB)  
   used     = 34518744 (32.919639587402344MB)  
   free     = 99633448 (95.01786041259766MB)  
   25.731032408326207% used  
Eden Space:  
   capacity = 134086656 (127.875MB)  
   used     = 34518744 (32.919639587402344MB)  
   free     = 99567912 (94.95536041259766MB)  
   25.743608670500368% used  
From Space:  
   capacity = 65536 (0.0625MB)  
   used     = 0 (0.0MB)  
   free     = 65536 (0.0625MB)  
   0.0% used  
To Space:  
   capacity = 65536 (0.0625MB)  
   used     = 0 (0.0MB)  
   free     = 65536 (0.0625MB)  
   0.0% used  
concurrent mark-sweep generation:  
   capacity = 671088640 (640.0MB)  
   used     = 287118912 (273.81793212890625MB)  
   free     = 383969728 (366.18206787109375MB)  
   42.7840518951416% used  
Perm Generation:  
   capacity = 100663296 (96.0MB)  
   used     = 41864504 (39.92510223388672MB)  
   free     = 58798792 (56.07489776611328MB)  
   41.58864816029867% used


jmap –histo pid 查询各种对象占用的内存大小。 

$ jmap -histo 5695 | less  
 num     #instances         #bytes  class name  
----------------------------------------------  
   1:        320290       63305456  [C  
   2:       1457010       46624320  java.util.concurrent.ConcurrentHashMap$Segment  
   3:       1502500       36060000  java.util.concurrent.locks.ReentrantLock$NonfairSync  
   4:         87785       29987632  [I  
   5:       1457010       23638928  [Ljava.util.concurrent.ConcurrentHashMap$HashEntry;  
   6:        285668       15240784  [Ljava.lang.Object;  
   7:         87239       10680160  <constMethodKlass>  
   8:        399482        9587568  java.lang.String  
   9:         16533        7466624  [B  
  10:         91065        7285072  [Ljava.util.concurrent.ConcurrentHashMap$Segment;  
  11:         87239        6983288  <methodKlass>  
  12:        125750        5868720  <symbolKlass>  
  13:         45409        5449080  java.net.SocksSocketImpl  
  14:         63574        4936176  [S  
  15:         45294        4710576  sun.nio.ch.SocketChannelImpl


jmap –permstat pid 查看Class Loader。 

jmap –dump:file=filename,format=b pid dump内存到文件。 

可以使用Jprofiler工具分析java dump文件。


本文转载自:http://sishuok.com/forum/blogPost/list/327.html

共有 人打赏支持
chape
粉丝 157
博文 305
码字总数 191349
作品 0
成都
程序员
《成神之路-基础篇》JVM——垃圾回收(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 Java之美[从菜鸟到高手演变]之JVM内存管理及垃圾回收 ...

⋅ 05/05 ⋅ 0

《成神之路-基础篇》JVM——JVM参数及调优(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 JVM参数及调优 JVM实用参数系列 成为Java GC专家(5)...

⋅ 05/05 ⋅ 0

面试中关于Java虚拟机(jvm)的问题看这篇就够了

最近看书的过程中整理了一些面试题,面试题以及答案都在我的文章中有所提到,希望你能在以问题为导向的过程中掌握虚拟机的核心知识。面试毕竟是面试,核心知识我们还是要掌握的,加油~~~ 下面...

snailclimb ⋅ 05/12 ⋅ 0

JVM性能调优实践——JVM篇

前言 在遇到实际性能问题时,除了关注系统性能指标。还要结合应用程序的系统的日志、堆栈信息、GClog、threaddump等数据进行问题分析和定位。关于性能指标分析可以参考前一篇JVM性能调优实践...

lijingyao8206 ⋅ 05/24 ⋅ 0

《成神之路-基础篇》JVM——JVM内存结构(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是《成神之路系列文章》的第一篇,主要是关于JVM的一些介绍。 持续更新中 参考文章: Java虚拟机的内存组成以及堆内存介绍 Java堆和栈...

⋅ 05/05 ⋅ 0

Java 面试知识点解析(三)——JVM篇

前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大部...

我没有三颗心脏 ⋅ 05/16 ⋅ 0

热修复与插件化基础——Java与Android虚拟机

一、Java虚拟机(JVM) 1、JVM整体结构 使用javac将java文件编译成class文件。 类加载器(ClassLoader)将class字节码加载进JVM对应的内存中。 JVM将内存分配给方法区、堆区、栈区、本地方式...

CSDN_LQR ⋅ 05/13 ⋅ 0

JVM汇总--jvm调优-命令篇

GC的最根本原因:垃圾收集器的工作就是清除Java创建的对象,垃圾收集器需要清理的对象数量以及要执行的GC数量均取决于已创建的对象数量。因此,为了使你的系统在GC上表现良好,首先需要减少创...

素雷 ⋅ 04/12 ⋅ 0

重磅!Java 性能监控调试工具 JMC 宣布开源

JRockit JVM 创始人之一、Oracle Java 产品组成员 Marcus Hirt 昨日在其博客上宣布,Java Mission Control(JMC)的源代码已正式开源。 JMC 是源自 JRockit JVM 的一套监控和管理工具,Oracl...

王练 ⋅ 05/07 ⋅ 6

甲骨文开源Java 性能监控调试工具 JMC

JMC (Java Mission Control) 是Oracle开源的Java 性能监控调试工具, 源自 JRockit JVM , 主要由三个组件构成:Java 进程浏览器、JMX 控制台和 Java Flight 记录器。 主要特性: Java 进程浏览...

marsdream ⋅ 05/07 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Linux中的端口大全

1 被LANA定义的端口 端口 名称 描述 1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat 用于列举连接了的端口的系统状态 13 d...

寰宇01 ⋅ 21分钟前 ⋅ 0

Confluence 6 如何备份存储文件和页面信息

备份的 ZIP 文件包含有 entities.xml,这个 XML 文件包含有 Confluence 的所有页面内容和存储附件的目录。 备份 Zip 文件结构 页面的附件是存储在附件存储目录中的,通过页面和附件 ID 进行识...

honeymose ⋅ 24分钟前 ⋅ 0

【每天一个JQuery特效】根据状态确定是否滑入或滑出被选元素

主要效果: 本文主要采用slideToggle()方法实现以一行代码同时实现以展开或收缩的方式显示或隐藏被选元素。 主要代码如下: <!DOCTYPE html><html><head><meta charset="UTF-8">...

Rhymo-Wu ⋅ 28分钟前 ⋅ 0

度量.net framework 迁移到.net core的工作量

把现有的.net framework程序迁移到.net core上,是一个非常复杂的工作,特别是一些API在两个平台上还不能同时支持。两个类库的差异性,通过人工很难识别全。好在微软的工程师们考虑到了我们顾...

李朝强 ⋅ 33分钟前 ⋅ 0

请不要在“微服务”的狂热中迷失自我!

微服务在过去几年一直是一个非常热门的话题(附录1)。何为“微服务的疯狂”,举个例子: 众所周知,Netflix在DevOps上的表现非常棒。Netfix可以做微服务。因此:如果我做微服务,我也将非常...

harries ⋅ 34分钟前 ⋅ 0

oAuth2 升级Spring Cloud Finchley.RELEASE踩坑分享

背景 6.19号,spring团队发布了期待已久的 Spring Cloud Finchley.RELEASE 版本。 重要变化: 基于Spring Boot 2.0.X 不兼容 Spring Boot 1.5.X 期间踩过几个坑,分享出来给大伙,主要是关于...

冷冷gg ⋅ 今天 ⋅ 0

OSChina 周一乱弹 —— 理发师小姐姐的魔法

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @冰冰棒- :分享田馥甄的单曲《My Love》 《My Love》- 田馥甄 手机党少年们想听歌,请使劲儿戳(这里) @Li-Wang :哎,头发又长了。。。又要...

小小编辑 ⋅ 今天 ⋅ 9

Kafka1.0.X_消费者API详解2

偏移量由消费者管理 kafka Consumer Api还提供了自己存储offset的功能,将offset和data做到原子性,可以让消费具有Exactly Once 的语义,比kafka默认的At-least Once更强大 消费者从指定分区...

特拉仔 ⋅ 今天 ⋅ 0

NEO智能合约之发布和升级(二)

接NEO智能合约之发布和升级(一),我们接下来说说智能合约的升级功能。 一 准备工作 合约的升级需要在合约内预先设置好升级接口,以方便在升级时调用。接下来我们对NEO智能合约之发布和升级...

红烧飞鱼 ⋅ 今天 ⋅ 0

个人博客的运营模式能否学习TMALL天猫质量为上?

心情随笔|个人博客的运营模式能否学习TMALL天猫质量为上? 中国的互联网已经发展了很多年了,记得在十年前,个人博客十分流行,大量的人都在写博客,而且质量还不错,很多高质量的文章都是在...

原创小博客 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部