java中jvm中非堆内存垃圾回收相关说明??
参考:https://www.jianshu.com/p/4004d36b64a4
jvm的垃圾回收机制大家应该已经很熟了,jvm主要是回收堆内存,而我我们在开发中会遇到在堆外分配内存的情况,那这部分内存是怎么回收的呢?
java中的堆外内存一般指DirectByteBuffer,他在高性能通信框架netty,mina中使用频繁,通常用来作为缓冲区。我们来看DirectByteBuffer的实现,如下图所示:
[图片]
可以发现底层是通过Unsafe类的allocateMemory方法,unsafe类通过调...
参考:https://www.jianshu.com/p/4004d36b64a4
jvm的垃圾回收机制大家应该已经很熟了,jvm主要是回收堆内存,而我我们在开发中会遇到在堆外分配内存的情况,那这部分内存是怎么回收的呢?
java中的堆外内存一般指DirectByteBuffer,他在高性能通信框架netty,mina中使用频繁,通常用来作为缓冲区。我们来看DirectByteBuffer的实现,如下图所示:
可以发现底层是通过Unsafe类的allocateMemory方法,unsafe类通过调用c++的方法来进行内存的分配,我们知道c++的内存可以通过析构方法来进行释放,然而java是通过JVM进行垃圾回收的,而JVM不会处理堆外内存,那java是如何回收Unsafe分配的堆外内存呢?
这里额外提一下Unsafe类,JDk是不推荐大家使用他的,因为直接操作底层系统,使程序脱离java的控制,所以他会被命名为"不安全的"。
通过构造函数可知,每创建一个DirectByteBuffer的同时都会创建一个Cleaner对象,Cleaner对象继承了PhantomReference即幽灵引用。关于java中的引用后面再写。PhantomReference主要是用来跟踪对象何时被回收的,它不能影响gc决策,但是gc过程中如果发现某个对象除了只有PhantomReference引用它之外,并没有其他的地方引用它了,那将会把这个引用放到java.lang.ref.Reference.pending队列里,在gc完毕的时候通知ReferenceHandler这个守护线程去执行一些后置处理,而DirectByteBuffer关联的PhantomReference是PhantomReference的一个子类,在最终的处理里会通过Unsafe的free接口来释放DirectByteBuffer对应的堆外内存块。
这里再摘抄一段美团点评技术博客Java魔法类:Unsafe应用解析中的解释:Cleaner继承自Java四大引用类型之一的虚引用PhantomReference(众所周知,无法通过虚引用获取与之关联的对象实例,且当对象仅被虚引用引用时,在任何发生GC的时候,其均可被回收),通常PhantomReference与引用队列ReferenceQueue结合使用,可以实现虚引用关联对象被垃圾回收时能够进行系统通知、资源清理等功能。如下图所示,当某个被Cleaner引用的对象将被回收时,JVM垃圾收集器会将此对象的引用放入到对象引用中的pending链表中,等待Reference-Handler进行相关处理。其中,Reference-Handler为一个拥有最高优先级的守护线程,会循环不断的处理pending链表中的对象引用,执行Cleaner的clean方法进行相关清理工作。所以当DirectByteBuffer仅被Cleaner引用(即为虚引用)时,其可以在任意GC时段被回收。当DirectByteBuffer实例对象被回收时,在Reference-Handler线程操作中,会调用Cleaner的clean方法根据创建Cleaner时传入的Deallocator来进行堆外内存的释放。
如下图所示:
在分配内存前,会调用Bits.reserveMemory方法,该方法中判断是否有足够内存进行分配,该内存大小可以通过-XX:MaxDirectMemorySize参数指定,或者默认值为“新生代的最大值-一个survivor的大小+老生代的最大值”。若没有足够内存时,会调用System.gc触发full gc,即主动的再触发一遍ReferenceHandler的后置处理。
这里特别说一下一个很多人都会遇到的坑(占小狼一篇文章就有提到):我们一般在jvm参数中会使用-XX:+DisableExplicitGC将System.gc关闭,主要为了防止程序员乱用导致系统发生不必要的gc从而影响性能,然而在使用了大量堆外内存的场景,比如使用netty框架开发时,这个参数是不能禁用的,因为其使用了大量的DirectByteBuffer。DirectByteBuffer对象关联了堆外内存,这些内存只有在DirectByteBuffer回收掉之后才有机会被回收,因此如果这些对象大部分都移到了old,但是一直没有触发CMS GC或者Full GC,那么物理内存将被耗尽,同时也要尽量使用-XX:MaxDirectMemorySize来指定最大的堆外内存大小
??
??
java中jvm中垃圾收集器和垃圾回收算法相关说明??
1、查看jvm默认垃圾回收方法:
java -XX:+PrintCommandLineFlags -version
x86默认:-XX:+UseParallelGC
2、垃圾回收算法优缺点:
ParallelGC
多个线程同时copy
优点:新生代回收更快。因为系统大部分时间做的gc都是新生代的,这样提高了cpu用于非gc时间
缺点:当运行在8G/16G server上老年代存活的对象太多时候中断时间过长
ParallelOldGC
分成多个独立的单元,如果单元中live object少则回收,多则跳过
优点:old generation上性能较 parallel...
1、查看jvm默认垃圾回收方法:
java -XX:+PrintCommandLineFlags -version
x86默认:-XX:+UseParallelGC
2、垃圾回收算法优缺点:
ParallelGC
多个线程同时copy
优点:新生代回收更快。因为系统大部分时间做的gc都是新生代的,这样提高了cpu用于非gc时间
缺点:当运行在8G/16G server上老年代存活的对象太多时候中断时间过长
ParallelOldGC
分成多个独立的单元,如果单元中live object少则回收,多则跳过
优点:old generation上性能较 parallel 方式有提高
缺点:大部分server系统old generation内存占用会达到60%-80%, 没有那么多理想的单元live object很少方便迅速回收,
同时 标记压缩算法 方面开销比起parallel并没明显减少。
ConcMarkSweepGC
同时不做 标记压缩算法 操作
优点:中断时间会降低, pause敏感
缺点:cpu占用过多,cpu密集型服务器不适合。另外碎片太多,每个object的存储都要通过链表连续跳n个地方,空间浪费问题也会增大
4、垃圾收集算法:mark-copy(标记-复制) 算法、“标记-清除”算法、mark-sweep-compact(标记-清除-整理)算法
5、垃圾回收方法详细介绍:
ConcMarkSweepGC(CMS):
这种回收策略的目标是提供短暂的停顿时间:
CMS收集器是基于“标记-清除”算法实现的
CMS也是Stop the application,但是:初始标记,确认哪些内存可以被回收是与业务线程同时执行的;
之后是重新标记阶段,这个阶段会Stop the application;之后是回收阶段,这个阶段是和业务线程同时执行着的
并发垃圾回收器(CMS):用户线程和垃圾收集线程同时执行(不一定是并行,可能交替执行),不需要停顿用户线程。
互联网公司多用它,适用于对响应时间有要求的场景。
使用 ParNew + CMS + Serial Old的收集器组合进行内存回收,Serial Old作为CMS出现“Concurrent Mode Failure”失败后的后备收集器使用。
CMS收集器主要有三个显著缺点:
1. CMS收集器对CPU资源非常敏感。在并发阶段,虽然不会导致用户线程停顿,但是会占用CPU资源而导致引用程序变慢,总吞吐量下降。
CMS默认启动的回收线程数是:(CPU数量+3)
/虚拟机提供了一种称为“增量式并发收集器”的CMS收集器变种,可以在并发标记、清理的时候让GC线程、用户线程交替运行,
尽量减少GC线程的独占资源的时间。
2. CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode
Failure“,失败后而导致另一次Full
GC的产生。由于CMS并发清理阶段用户线程还在运行,伴随程序的运行自热会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,
CMS无法在本次收集中处理它们,只好留待下一次GC时将其清理掉。这一部分垃圾称为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,
即需要预留足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,
需要预留一部分内存空间提供并发收集时的程序运作使用。在默认设置下,CMS收集器在老年代使用了68%的空间时就会被激活,
也可以通过参数-XX:CMSInitiatingOccupancyFraction的值来提供触发百分比,以降低内存回收次数提高性能。
要是CMS运行期间预留的内存无法满足程序其他线程需要,就会出现“Concurrent
Mode Failure”失败,这时候虚拟机将启动后备预案:临时启用Serial
Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。所以说参数-XX:CMSInitiatingOccupancyFraction设置的过高将会很容易致“Concurrent
Mode Failure”失败,性能反而降低。
3. 碎片化,最后一个缺点,CMS是基于“标记-清除”算法实现的收集器,使用“标记-清除”算法收集后,会产生大量碎片。空间碎片太多时,
将会给对象分配带来很多麻烦,比如说大对象,内存空间找不到连续的空间来分配不得不提前触发一次Full
GC。为了解决这个问题,CMS收集器提供了一个-XX:UseCMSCompactAtFullCollection开关参数,用于在Full
GC之后增加一个碎片整理过程,还可通过-XX:CMSFullGCBeforeCompaction参数设置执行多少次不压缩的Full
GC之后,跟着来一次碎片整理过程。
ParallelGC:
ParaellGC是Stop the application,之后多个线程去收集可回收的内存,之后执行回收操作,
关键点是:确认哪些内存可以回收、之后再回收,俩个操作都在Stop application后才执行的。
并行垃圾回收器(Parallel):多个垃圾回收线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景。
-XX:+UseParallelGCJvm运行在Server模式下的默认值,打开此开关后,使用Parallel Scavenge + Serial Old的收集器组合进行回收
ParallelOldGC:
相对于串行GC而言,顾名思义,并行GC可以通过并行执行来减少GC时间,其使用的算法和串行GC一样,
也是对年轻代使用 mark-copy(标记-复制) 算法,对老年代使用 mark-sweep-compact(标记-清除-整理)算法,
但是在标记和复制/整理阶段都会使用多个线程。因此适用于多核处理器。它的JVM参数配置可以使用-XX:+UseParallelGC 或-XX:+UseParallelOldGC
Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
-XX:+UseParallelOldGC使用Parallel Scavenge + Parallel Old的收集器组合进行回收
Serial收集器(复制算法):新生代单线程收集器,标记和清理都是单线程,优点是简单高效。
Serial Old收集器(标记-整理算法):老年代单线程收集器,Serial收集器的老年代版本。
ParNew收集器(停止-复制算法):新生代收集器,可以认为是Serial收集器的多线程版本,在多核CPU环境下有着比Serial更好的表现。
Parallel Scavenge 收集器(停止-复制算法):并行收集器,追求高吞吐量,高效利用CPU。吞吐量一般为99%,
吞吐量= 用户线程时间/(用户线程时间+GC线程时间)。适合后台应用等对交互相应要求不高的场景。
Parallel Old收集器(停止-复制算法):Parallel Scavenge收集器的老年代版本,并行收集器,吞吐量优先
CMS(Concurrent Mark Sweep)收集器(标记-清理算法):高并发、低停顿,追求最短GC回收停顿时间,cpu占用比较高,响应时间快,停顿时间短,
多核cpu 追求高响应时间的选择
??
??
近期想跳槽,要面试的Java程序员,查漏补缺,以便尽快弥补短板;
想了解“一线互联网公司”最新技术要求,对比找出自身的长处和弱点所在,评估自己在现有市场上的竞争力如何;
做了几年Java开发,但还没形成系统的Java知识体系,缺乏清晰的提升方向和学习路径的程序员。
相信它会给大家带来很多收获。
近期想跳槽,要面试的Java程序员,查漏补缺,以便尽快弥补短板;
想了解“一线互联网公司”最新技术要求,对比找出自身的长处和弱点所在,评估自己在现有市场上的竞争力如何;
做了几年Java开发,但还没形成系统的Java知识体系,缺乏清晰的提升方向和学习路径的程序员。
相信它会给大家带来很多收获。
java中jdk中使用keytool工具生成自签名证书相关说明??
1 生成根证书CA
1.1 --生成根证书
set keystore=oa.keystore
set alias=rootca
set storepass=changeit
set keypass=changeit
set DNAME="CN=ChuanYeCA, OU=ChuanYe, O=ChuanYe, L=BeiJing, ST=BeiJing, C=CN"
set validity=3650
keytool -genkeypair -alias %alias% -keyalg RSA -keysize 2048 -sigalg...
1 生成根证书CA
1.1 --生成根证书
set keystore=oa.keystore
set alias=rootca
set storepass=changeit
set keypass=changeit
set DNAME="CN=ChuanYeCA, OU=ChuanYe, O=ChuanYe, L=BeiJing, ST=BeiJing, C=CN"
set validity=3650
keytool -genkeypair -alias %alias% -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -keystore %keystore% -storetype jks -storepass %storepass% -keypass %keypass% -dname %DNAME% -validity %validity%
1.2 --导出根证书
keytool -exportcert -keystore oa.keystore -storepass changeit -file rootca.cer -alias rootca
1.3 --导入证书到truststore中
keytool -import -alias trustrootca -file rootca.cer -storepass changeit -keystore oa.truststore
2 --生成二级CA
2.1--生成二级证书
set keystore=oa.keystore
set alias=subca
set storepass=changeit
set keypass=changeit
set DNAME="CN=SubCA, OU=ChuanYe Sub, O=ChuanYe Sub, L=BeiJing, ST=BeiJing, C=CN"
set validity=3650
keytool -genkeypair -alias %alias% -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -keystore %keystore% -storetype jks -storepass %storepass% -keypass %keypass% -dname %DNAME% -validity %validity%
2.2 --从二级CA的秘钥对中生成证书请求
keytool -certreq -alias subca -keystore oa.keystore -storepass changeit -file subca.csr
2.3 --使用证书请求从根CA中签发证书
keytool -gencert -alias rootca -keystore oa.keystore -storepass changeit -infile subca.csr -outfile subca.cer
2.4 --导入二级CA到秘钥库中
#keytool -importcert -v -trustcacerts -alias subca -file subca.cer -storepass changeit -keystore oa.keystore
keytool -importcert -alias subca -file subca.cer -storepass changeit -keystore oa.keystore
2.5 --导入证书到truststore中
keytool -import -alias trustsubca -file subca.cer -storepass changeit -keystore oa.truststore
3 使用二级证书签发用户证书
3.1 --生成用户证书
set keystore=oa.keystore
set alias=shayne
set storepass=changeit
set keypass=changeit
set DNAME="CN=192.168.1.100, OU=SH, O=SH, L=BeiJing, ST=BeiJing, C=CN"
set validity=3650
keytool -genkeypair -alias %alias% -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -keystore %keystore% -storetype jks -storepass %storepass% -keypass %keypass% -dname %DNAME% -validity %validity%
3.2 --导出用户证书请求
keytool -certreq -alias shayne -keystore oa.keystore -storepass changeit -file shayne.csr
3.3 --用二级CA签发用户证书
keytool -gencert -alias subca -keystore oa.keystore -storepass changeit -infile shayne.csr -outfile shayne.cer
3.4 --导入用户证书到秘钥库中
keytool -importcert -alias shayne -file shayne.cer -storepass changeit -keystore oa.keystore
4 --导入证书到truststore中
keytool -import -alias trustuserca -file shayne.cer -storepass changeit -keystore oa.truststore
5 --生成p12格式证书
keytool -importkeystore -srckeystore oa.keystore -destkeystore client.p12 -srcalias rootca -destalias rootca -srcstorepass changeit -deststorepass changeit -srcstoretype jks -deststoretype pkcs12 -noprompt
#生成p12格式证书
keytool -importkeystore -srckeystore serverKey.jks -destkeystore client.p12 -srcalias key_alias -destalias key_alias -srcstoretype jks -deststoretype pkcs12 -noprompt
#查看证书
keytool -list -storepass Psbcoa12345! -keystore serverKey.jks
#删除证书
keytool -delete -alias ca_alias -storepass Psbcoa12345! -keystore serverKey.jks
参考:[生成CA和二级CA证书]:https://www.hellojava.com/a/76445.html
java中jdk中iostat查看磁盘io和cpu统计信息命令相关说明??
参考:https://blog.csdn.net/weixin_38428439/article/details/121525172
概述
iostat 主要用于输出磁盘IO 和 CPU的统计信息。
iostat属于sysstat软件包。可以用yum install sysstat 直接安装。
iostat 用法
用法:iostat [选项] [<时间间隔>] [<次数>]
??
??
参考:https://blog.csdn.net/weixin_38428439/article/details/121525172
概述
iostat 主要用于输出磁盘IO 和 CPU的统计信息。
iostat属于sysstat软件包。可以用yum install sysstat 直接安装。
iostat 用法
用法:iostat [选项] [<时间间隔>] [<次数>]
??
??
java中that contained an invalid cookie解决方法相关说明??
参考:https://blog.csdn.net/weixin_45578033/article/details/105407266
tongweb容器启动现象:
A cookie header was received[xxxxxx] that contained an invalid cookie. That cookie will be ignore.
解决方法(tomcat为例):
1.在context.xml中配置
旧版中,修改${catalina.home}/conf/server.xml如下
<CookieProcessor className="org...
参考:https://blog.csdn.net/weixin_45578033/article/details/105407266
tongweb容器启动现象:
A cookie header was received[xxxxxx] that contained an invalid cookie. That cookie will be ignore.
解决方法(tomcat为例):
1.在context.xml中配置
旧版中,修改${catalina.home}/conf/server.xml如下
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor"/></Context>
Tomcat8/9修改context.xml如下
<CookieProcessor className ="org.apache.tomcat.util.http.LegacyCookieProcessor"/></Context>
2.在启动项中配置
@Bean
public WebServerFactoryCustomizer cookieProcessorCustomizer() {undefined
return (factory) -> factory.addContextCustomizers(
(context) -> context.setCookieProcessor(new LegacyCookieProcessor()));
}
??
??
java中XHRcrosserror跨域问题解决方法相关说明??
参考:https://blog.csdn.net/bohu83/article/details/114046354
一 问题现象
??
二 新增拦截器代码
以下为springboot bean注入方式。
??
三 在原来的拦截器配置增加配置
注意setorder 数字越小优先级越高。这个放在@Configuration 类里面。
??
四 NG配置
配置内容如下:
location / {
add_header Access-Control-Allow-Origin...
参考:https://blog.csdn.net/bohu83/article/details/114046354
一 问题现象
??
二 新增拦截器代码
以下为springboot bean注入方式。
??
三 在原来的拦截器配置增加配置
注意setorder 数字越小优先级越高。这个放在@Configuration 类里面。
??
四 NG配置
配置内容如下:
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
五 VUE前端配置
配置内容如下:
$.ajax({
url: "https://b.com/method",
type: 'POST',
data: requestParams,
dataType: 'json',
xhrFields: {
withCredentials: true
},
crossDomain: true,
async: false,
...
注:容易出问题的地方,url 只写path,不写明HTTP协议。参数不加上跨域请求。
??
??