首页 文章 精选 留言 我的

精选列表

搜索[策略模式],共10000篇文章
优秀的个人博客,低调大师

深入理解JVM(三)——垃圾收集策略详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34173549/article/details/79612610 Java虚拟机的内存模型分为五个部分,分别是:程序计数器、Java虚拟机栈、本地方法栈、堆、方法区。 这五个区域既然是存储空间,那么为了避免Java虚拟机在运行期间内存存满的情况,就必须得有一个垃圾收集者的角色,不定期地回收一些无效内存,以保障Java虚拟机能够健康地持续运行。 这个垃圾收集者就是平常我们所说的“垃圾收集器”,那么垃圾收集器在何时清扫内存?清扫哪些数据?这就是接下来我们要解决的问题。 程序计数器、Java虚拟机栈、本地方法栈都是线程私有的,也就是每条线程都拥有这三块区域,而且会随着线程的创建而创建,线程的结束而销毁。那么,垃圾收集器在何时清扫这三块区域的问题就解决了。 此外,Java虚拟机栈、本地方法栈中的栈帧会随着方法的开始而入栈,方法的结束而出栈,并且每个栈帧中的本地变量表都是在类被加载的时候就确定的。因此以上三个区域的垃圾收集工作具有确定性,垃圾收集器能够清楚地知道何时清扫这三块区域中的哪些数据。 然而,堆和方法区中的内存清理工作就没那么容易了。堆和方法区所有线程共享,并且都在JVM启动时创建,一直得运行到JVM停止时。因此它们没办法根据线程的创建而创建、线程的结束而释放。 堆中存放JVM运行期间的所有对象,虽然每个对象的内存大小在加载该对象所属类的时候就确定了,但究竟创建多少个对象只有在程序运行期间才能确定。方法区中存放类信息、静态成员变量、常量。类的加载是在程序运行过程中,当需要创建这个类的对象时才会加载这个类。因此,JVM究竟要加载多少个类也需要在程序运行期间确定。因此,堆和方法区的内存回收具有不确定性,因此垃圾收集器在回收堆和方法区内存的时候花了一些心思。 堆内存的回收 1. 如何判定哪些对象需要回收? 在对堆进行对象回收之前,首先要判断哪些是无效对象。我们知道,一个对象不被任何对象或变量引用,那么就是无效对象,需要被回收。一般有两种判别方式: 引用计数法每个对象都有一个计数器,当这个对象被一个变量或另一个对象引用一次,该计数器加一;若该引用失效则计数器减一。当计数器为0时,就认为该对象是无效对象。 可达性分析法所有和GC Roots直接或间接关联的对象都是有效对象,和GC Roots没有关联的对象就是无效对象。GC Roots是指: Java虚拟机栈所引用的对象(栈帧中局部变量表中引用类型的变量所引用的对象) 方法区中静态属性引用的对象 方法区中常量所引用的对象 本地方法栈所引用的对象PS:注意!GC Roots并不包括堆中对象所引用的对象!这样就不会出现循环引用。 两者对比:引用计数法虽然简单,但存在一个严重的问题,它无法解决循环引用的问题。因此,目前主流语言均使用可达性分析方法来判断对象是否有效。 2. 回收无效对象的过程 当JVM筛选出失效的对象之后,并不是立即清除,而是再给对象一次重生的机会,具体过程如下: 判断该对象是否覆盖了finalize()方法 若已覆盖该方法,并该对象的finalize()方法还没有被执行过,那么就会将finalize()扔到F-Queue队列中; 若未覆盖该方法,则直接释放对象内存。 执行F-Queue队列中的finalize()方法虚拟机会以较低的优先级执行这些finalize()方法们,也不会确保所有的finalize()方法都会执行结束。如果finalize()方法中出现耗时操作,虚拟机就直接停止执行,将该对象清除。 对象重生或死亡如果在执行finalize()方法时,将this赋给了某一个引用,那么该对象就重生了。如果没有,那么就会被垃圾收集器清除。 注意:强烈不建议使用finalize()函数进行任何操作!如果需要释放资源,请使用try-finally。因为finalize()不确定性大,开销大,无法保证顺利执行。 方法区的内存回收 我们知道,如果使用复制算法实现堆的内存回收,堆就会被分为新生代和老年代,新生代中的对象“朝生夕死”,每次垃圾回收都会清除掉大量的对象;而老年代中的对象生命较长,每次垃圾回收只有少量的对象被清除掉。 由于方法区中存放生命周期较长的类信息、常量、静态变量,因此方法区就像是堆的老年代,每次垃圾收集的只有少量的垃圾被清除掉。 方法区中主要清除两种垃圾:1. 废弃常量2. 废弃的类 1. 如何判定废弃常量? 清除废弃的常量和清除对象类似,只要常量池中的常量不被任何变量或对象引用,那么这些常量就会被清除掉。 2. 如何废弃废弃的类? 清除废弃类的条件较为苛刻:1. 该类的所有对象都已被清除2. 该类的java.lang.Class对象没有被任何对象或变量引用只要一个类被虚拟机加载进方法区,那么在堆中就会有一个代表该类的对象:java.lang.Class。这个对象在类被加载进方法区的时候创建,在方法区中该类被删除时清除。3. 加载该类的ClassLoader已经被回收 垃圾收集算法 现在我们知道了判定一个对象是无效对象、判定一个类是废弃类、判定一个常量是废弃常量的方法,也就是知道了垃圾收集器会清除哪些数据,那么接下来介绍如何清除这些数据。 1. 标记-清除算法 首先利用刚才介绍的方法判断需要清除哪些数据,并给它们做上标记;然后清除被标记的数据。 分析:这种算法标记和清除过程效率都很低,而且清除完后存在大量碎片空间,导致无法存储大对象,降低了空间利用率。 2. 复制算法 将内存分成两份,只将数据存储在其中一块上。当需要回收垃圾时,也是首先标记出废弃的数据,然后将有用的数据复制到另一块内存上,最后将第一块内存全部清除。 分析:这种算法避免了碎片空间,但内存被缩小了一半。而且每次都需要将有用的数据全部复制到另一片内存上去,效率不高。 解决空间利用率问题:在新生代中,由于大量的对象都是“朝生夕死”,也就是一次垃圾收集后只有少量对象存活,因此我们可以将内存划分成三块:Eden、Survior1、Survior2,内存大小分别是8:1:1。分配内存时,只使用Eden和一块Survior1。当发现Eden+Survior1的内存即将满时,JVM会发起一次MinorGC,清除掉废弃的对象,并将所有存活下来的对象复制到另一块Survior2中。那么,接下来就使用Survior2+Eden进行内存分配。 通过这种方式,只需要浪费10%的内存空间即可实现带有压缩功能的垃圾收集方法,避免了内存碎片的问题。 但是,当一个对象要申请内存空间时,发现Eden+Survior中剩下的空间无法放置该对象,此时需要进行Minor GC,如果MinorGC过后空闲出来的内存空间仍然无法放置该对象,那么此时就需要将对象转移到老年代中,这种方式叫做“分配担保”。 什么是分配担保?当JVM准备为一个对象分配内存空间时,发现此时Eden+Survior中空闲的区域无法装下该对象,那么就会触发MinorGC,对该区域的废弃对象进行回收。但如果MinorGC过后只有少量对象被回收,仍然无法装下新对象,那么此时需要将Eden+Survior中的所有对象都转移到老年代中,然后再将新对象存入Eden区。这个过程就是“分配担保”。 3. 标记-整理算法 在回收垃圾前,首先将所有废弃的对象做上标记,然后将所有未被标记的对象移到一边,最后清空另一边区域即可。 分析:它是一种老年代的垃圾收集算法。老年代中的对象一般寿命比较长,因此每次垃圾回收会有大量对象存活,因此如果选用“复制”算法,每次需要复制大量存活的对象,会导致效率很低。而且,在新生代中使用“复制”算法,当Eden+Survior中都装不下某个对象时,可以使用老年代的内存进行“分配担保”,而如果在老年代使用该算法,那么在老年代中如果出现Eden+Survior装不下某个对象时,没有其他区域给他作分配担保。因此,老年代中一般使用“标记-整理”算法。 4. 分代收集算法 将内存划分为老年代和新生代。老年代中存放寿命较长的对象,新生代中存放“朝生夕死”的对象。然后在不同的区域使用不同的垃圾收集算法。 Java中引用的种类 Java中根据生命周期的长短,将引用分为4类。 1. 强引用 我们平时所使用的引用就是强引用。A a = new A();也就是通过关键字new创建的对象所关联的引用就是强引用。只要强引用存在,该对象永远也不会被回收。 2. 软引用 只有当堆即将发生OOM异常时,JVM才会回收软引用所指向的对象。软引用通过SoftReference类实现。软引用的生命周期比强引用短一些。 3. 弱引用 只要垃圾收集器运行,软引用所指向的对象就会被回收。弱引用通过WeakReference类实现。弱引用的生命周期比软引用短。 4. 虚引用 虚引用也叫幽灵引用,它和没有引用没有区别,无法通过虚引用访问对象的任何属性或函数。一个对象关联虚引用唯一的作用就是在该对象被垃圾收集器回收之前会受到一条系统通知。虚引用通过PhantomReference类来实现。

优秀的个人博客,低调大师

【短视频SDK】短视频SDK License的策略

1.概述 短视频SDK的使用前提是需要开通License的,否则用户集成SDK将会不可用.目前需要用户提供一些基础信息发送到我们的服务邮箱来保证SDK可用.整体用户需要保证提供的信息的准确性.SDK需要保证服务的稳定性和可用性. 2.需要提供的参数 iOS: 应用bundleIDAndroid:包名和签名信息(MD5、格式小写无冒号) 2.1 bundleId如何获取? 你可以直接使用xCode查看,也可以通过代码获取: //代码段示例 [[NSBundle mainBundle] bundleIdentifier] 2.2 包名和签名信息如何获取? 注:获取签名有个点需要明确,绑定的keystore不一样,得到的MD5信息也不一样,如不指定keystore默认拿到的debug包是自己本地的debug.keystore. 如何指定keystore呢

优秀的个人博客,低调大师

谷歌希望通过全新应用下载策略杀死Facebook

从现在的情况来看,移动应用装机量似乎已经成为了谷歌和Facebook竞争的又一前沿阵地。 目前,谷歌已经开始让部分Android用户在无需登陆谷歌Play商店的前提下,直接从搜索结果页面下载应用。消息称,目前这一功能正处于测试阶段,在用户触发了下载窗口后,搜索页面上便会出现一个权限询问小窗和安装按钮,这和谷歌Play商店里的形式十分类似。 尽管这一功能尚未全面推出,但这一举措显而易见将对Facebook近年来增速最快的业务产生巨大影响。数年前,Facebook曾推出了移动应用安装广告,这让消费者可以更加轻松的找到、下载自己需要的应用程序。 目前,绝大多数移动应用安装广告会出现在Facebook的信息流中,并让用户以最快的速度点击、安装应用。对于许多应用开发者而言,Facebook的移动应用安装广告投放也是自己让产品从其他竞争对手中脱颖而出的一个自然选择。有数据显示,Facebook曾借助移动应用安装广告取得了丰厚的移动广告营收。举例来说,这一业务在2014年第一季度在其总营收中的占比达到59%,高于此前一年的30%。而且在这类广告中,广告主可以根据年龄、地理位置、性别和兴趣等重要因素对目标用户进行定位。 然而,如果谷歌开始全面推行让用户直接在搜索结果页面中下载应用的战略,Facebook移动应用安装广告的受欢迎度势必会受到很大影响。尽管Facebook一直拒绝透露移动应用安装广告在公司整体营收中的最新贡献比例,但分析人士相信这一业务已经成为了目前Facebook移动广告业务中最重要的一个环节。 对于谷歌而言,这一全新尝试则使谷歌搜索再一次向人性化靠拢了一步。去年晚些时候,谷歌推出了“应用流”功能。通过这一功能,用户可以在谷歌搜索结果中与应用内容流互动,使得下载移动应用变得不再必要。举例来说,当用户在没有安装旅行应用的时候准备出行,他完全只需通过一次搜索完成预订,而无需特地去下载专门的应用程序。 此外,该公司还在去年尝试推出了“60秒应用试用”服务,顾名思义就是让消费者在广告中先试用60秒再决定是否购买、下载这个应用。就目前而言,谷歌正在测试的直接从搜索结果页面下载应用的服务仅仅适用于谷歌原生搜索,但我们相信这一服务有望在未来覆盖更多平台。 BI旗下调研部门BI Intelligence数据显示,全球移动应用安装广告营收有望在2019年底增长至68亿美元,虽然谷歌大力推行的从搜索结果页面下载应用的服务并不意味着Facebook的末日,但这一举措显而易见会影响Android应用开发者在支配应用广告预算时候的选择,并帮助该公司从这个价值68亿美元的大蛋糕中分一杯羹。 Facebook方面此前曾解释称,公司平台上的移动应用安装广告之所以对于开发者有如此大的吸引力主要是因为,他们可以根据Facebook获悉的用户信息更好的将这类应用向目标用户进行定向推送。不过,谷歌的这一服务也同样会带来一个额外的好处,那就是应用开发者能够清楚的掌握用户会在什么时候搜索自己想要的某类应用。 本文转自d1net(转载)

优秀的个人博客,低调大师

Gmail 即将落实阻止 JavaScript 的安全策略

据外媒报道,Gmail 将很快部署阻止 JavaScript 电邮附件运行的措施。从 2月13日起,用户将无法再添加 .js 类型的附件,因其被很多形式的恶意攻击所利用。如果用户不小心下载了一个恶意 JavaScript 文件,攻击者可以利用它来获得 PC 的访问权限,窃取数据或执行其它破坏性操作。 Android Police 指出,JavaScript 已成为继 .exe .bat .msc 之后,被 Gmail 严格限制分享的又一个附件类型。 虽然此举无法彻底杜绝被嵌入 .zip 等压缩包中的恶意文件,但斩断直接发送的途径,对大多数普通用户来说确实是件有助于提升 Gmail 邮件服务安全性的好事。 如果你有特殊的需求,也可以考虑通过谷歌网盘或云存储等方式,发送和分享一个 JavaScript 文件。 试图发送此类附件的 Gmail 用户,将会看到一则“禁止上传”的警告提示(收件人那边暂不清楚)。 文章转载自 开源中国社区 [http://www.oschina.net]

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册