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

如皋建设局网站网站管理员是干什么的

如皋建设局网站,网站管理员是干什么的,免费软件下载网,网页制作专业知识目录 垃圾判断算法#xff08;你是不是垃圾#xff1f;#xff09; 引用计数法 可达性算法 对象的引用 强引用 软引用 弱引用 虚引用 对象的自我救赎 垃圾回收算法--分代 标记清除算法 复制算法 标记整理法 垃圾处理器 垃圾判断算法#xff08;你是不是垃圾你是不是垃圾 引用计数法 可达性算法 对象的引用 强引用 软引用 弱引用 虚引用 对象的自我救赎 垃圾回收算法--分代 标记清除算法 复制算法 标记整理法 垃圾处理器 垃圾判断算法你是不是垃圾 引用计数法 最容易想到的一种方式是引用计数法啥叫引用计数法简单地说就是对象被引用一次在它的对象头上加一次引用次数如果没有被引用引用次数为 0则此对象可回收 String ref new String(Java); 以上代码 ref 引用了右侧定义的对象所以引用次数是 1   如果在上述代码后面添加一个 ref null则由于对象没被引用引用次数置为 0由于不被任何变量引用此时即被回收动图如下 看起来用引用计数确实没啥问题了不过它无法解决一个主要的问题循环引用啥叫循环引用 public class TestRC { TestRC instance; public TestRC(String name) { } public static void main(String[] args) { // 第一步 TestRC a new TestRC(a); TestRC b new TestRC(b); // 第二步 a.instance b; b.instance a; // 第三步 a null; b null; } } 按步骤一步步画图 到了第三步虽然 ab 都被置为 null 了但是由于之前它们指向的对象互相指向了对方引用计数都为 1所以无法回收也正是由于无法解决循环引用的问题所以现代虚拟机都不用引用计数法来判断对象是否应该被回收。 可达性算法 现代虚拟机基本都是采用这种算法来判断对象是否存活可达性算法的原理是以一系列叫做 GC Root 的对象为起点出发引出它们指向的下一个节点再以下个节点为起点引出此节点指向的下一个结点。这样通过 GC Root 串成的一条线就叫引用链直到所有的结点都遍历完毕, 如果相关对象不在任意一个以 GC Root 为起点的引用链中则这些对象会被判断为「垃圾」, 会被 GC 回收。 如图示如果用可达性算法即可解决上述循环引用的问题因为从GC Root 出发没有到达 a,b, 所以 ab 可回收 a, b 对象可回收就一定会被回收吗? 并不是对象的 finalize 方法给了对象一次垂死挣扎的机会当对象不可达可回收时当发生 GC 时会先判断对象是否执行了 finalize 方法如果未执行则会先执行 finalize 方法我们可以在此方法里将当前对象与 GC Roots 关联这样执行 finalize 方法之后GC 会再次判断对象是否可达如果不可达则会被回收如果可达则不回收 注意 finalize 方法只会被执行一次如果第一次执行 finalize 方法此对象变成了可达确实不会回收但如果对象再次被 GC则会忽略 finalize 方法对象会被回收这一点切记! 虽然可达性分析算法解决了循环依赖的问题但是也产生了许多新的问题。进行可达性分析搜索的过程是需要时间的而此时程序也是在并行运行着不断产生新的对象丢弃无用的对象。整个内存的状态是在变化的所以目前主流的垃圾回收算法大多都要进行一种操作 Stop-The-World翻译过来即停止世界即暂停所有的用户线程避免内存堆的状态发生变化。 那么这些 GC Roots 到底是什么东西呢哪些对象可以作为 GC Root 呢有以下几类 虚拟机栈栈帧中的本地变量表中引用的对象方法区中类静态属性引用的对象方法区中常量引用的对象本地方法栈中 JNI即一般说的 Native 方法引用的对象 虚拟机栈中引用的对象 如下代码所示a 是栈帧中的本地变量当 a null 时由于此时 a 充当了 GC Root 的作用a 与原来指向的实例 new Test() 断开了连接所以对象会被回收。 public class Test {public static void main(String[] args) {Test a new Test(); a null; } } 方法区中类静态属性引用的对象 如下代码所示当栈帧中的本地变量 a null 时由于 a 原来指向的对象与 GC Root (变量 a) 断开了连接所以 a 原来指向的对象会被回收而由于我们给 s 赋值了变量的引用s 在此时是类静态属性引用充当了 GC Root 的作用它指向的对象依然存活! public class Test {public static Test s; public static void main(String[] args) {Test a new Test(); Test.s new Test(); a null; } } 方法区中常量引用的对象 如下代码所示常量 s 指向的对象并不会因为 a 指向的对象被回收而回收 public class Test {public static final Test s new Test(); public static void main(String[] args) { Test a new Test(); a null; } } 本地方法栈中 JNI即一般说的 Native 方法引用的对象 方法调用中的时候是作为 GC Root 如果方法调用完成了这些 JNI 引用对象是可以被回收的如果不想要这些 JNI 引用对象被回收可以设置为全局变量。 如果想让某些局部引用在从 C 函数返回后不被 JVM 回收则可以借助 JNI 函数 NewGlobalRef将该局部引用转换为全局引用。被全局引用的对象不会被 JVM 回收只能通过 JNI 函数 DeleteGlobalRef 消除全局引用后才可以被回收。 这是简单给不清楚本地方法为何物的童鞋简单解释一下所谓本地方法就是一个 java 调用非 java 代码的接口该方法并非 Java 实现的可能由 C 或 Python 等其他语言实现的 Java 通过 JNI 来调用本地方法 而本地方法是以库文件的形式存放的在 WINDOWS 平台上是 DLL 文件形式在 UNIX 机器上是 SO 文件形式。 当调用 Java 方法时虚拟机会创建一个栈桢并压入 Java 栈而当它调用的是本地方法时虚拟机会保持 Java 栈不变不会在 Java 栈祯中压入新的祯虚拟机只是简单地动态连接并直接调用指定的本地方法。 JNIEXPORT void JNICALL Java_com_pecuyu_jnirefdemo_MainActivity_newStringNative(JNIEnv *env, jobject instancejstring jmsg) {... // 缓存String的class jclass jc (*env)-FindClass(env, STRING_PATH);} 如上代码所示当 java 调用以上本地方法时jc 会被本地方法栈压入栈中, jc 就是我们说的本地方法栈中 JNI 的对象引用因此只会在此本地方法执行完成后才会被释放。一旦从 C 函数中返回至 Java 方法中那么局部引用将会失效JVM 在整个 Tracing 过程中就不再考虑这些局部引用也就是说一段时间后局部引用占用的内存将会被回收。 对象的引用 无论是通过引用计数算法判断对象的引用数量还是通过可达性分析算法判断对象是否引用链可达判定对象是否存活都和“引用”离不开关系。 在JDK 1.2版之前Java里面的引用是很传统的定义如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址就称该reference数据是代表某块内存、某个对象的引用。这种定义并没有什么不对只是现在看来有些过于狭隘了一个对象在这种定义下只有“被引用”或者“未被引用”两种状态对于描述一些“食之无味弃之可惜”的对象就显得无能为力。譬如我们希望能描述一类对象当内存空间还足够时能保留在内存之中如果内存空间在进行垃圾收集后仍然非常紧张那就可以抛弃这些对象——很多系统的缓存功能都符合这样的应用场景。 在JDK 1.2版之后Java对引用的概念进行了扩充将引用分为强引用Strongly Re-ference、软引用Soft Reference、弱引用Weak Reference和虚引用Phantom Reference4种这4种引用强度依次逐渐减弱。 并不是说只要是和 GC Roots 有一条联系Reference Chain对象就是存活的它还与对象引用级别有关。 强引用 属于普通常见的那种也就是我们 new 出来的对象无论任何情况下只要强引用关系还存在垃圾收集器就永远不会回收掉被引用的对象。 软引用 只被软引用关联着的对象在系统将要发生内存溢出异常前会把这些对象列进回收范围之中进行第二次回收如果这次回收还没有足够的内存才会抛出内存溢出异常。在JDK 1.2版之后提供了SoftReference类来实现软引用。 弱引用 弱引用也是用来描述那些非必须对象但是它的强度比软引用更弱一些被弱引用关联的对象只能生存到下一次垃圾收集发生为止不太对如果是 Young GC 不一定会回收如果是 Full GC 则一定会回收参考下面例子。当垃圾收集器开始工作无论当前内存是否足够都会回收掉只被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。 虚引用 虚引用也称为“幽灵引用”或者“幻影引用”它是最弱的一种引用关系。一个对象是否有虚引用的存在完全不会对其生存时间构成影响也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2版之后提供了PhantomReference类来实现虚引用。 栗子说明一下 添加配置JVM参数 -XX:PrintGC -XX:PrintGCDateStamps -Xmx5m -Xms5m public class test {static class MyOb {private int i 1;// 覆盖finalize()方法Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println( obj [ this.toString() ] is gc );}}// 消耗大量内存public static void drainMemory() {String[] array new String[1024 * 10];for(int i 0; i 1024 * 10; i) {for(int j a; j e; j) {array[i] (char)j;}}} } 首先先写一个 覆盖 finalize 方法的对象进行 GC 的时候会进入另外有个消耗大量内存的方法。 public static void main(String[] args) {MyOb ob new MyOb();drainMemory();} 强引用的我们看看输出 2020-08-28T16:33:56.5460800: [GC (Allocation Failure) 1024K-616K(5632K), 0.0011773 secs] 2020-08-28T16:33:56.5780800: [GC (Allocation Failure) 1633K-827K(5632K), 0.0006751 secs] 2020-08-28T16:33:56.5910800: [GC (Allocation Failure) 1851K-1049K(5632K), 0.0022424 secs] 2020-08-28T16:33:56.5940800: [GC (Allocation Failure) 2073K-1273K(5632K), 0.0010249 secs] 2020-08-28T16:33:56.5960800: [GC (Allocation Failure) 2297K-1521K(5632K), 0.0011336 secs] 明显内存不足进行 GC 的时候判断到 ob 可达的是不会进行回收的。 然后看看软引用 public static void main(String[] args) {SoftReferenceMyOb ob new SoftReference(new MyOb());drainMemory();} 2020-08-28T16:37:38.7300800: [GC (Allocation Failure) 1024K-584K(5632K), 0.0013387 secs] 2020-08-28T16:37:38.7640800: [GC (Allocation Failure) 1601K-842K(5632K), 0.0007544 secs] 2020-08-28T16:37:38.7840800: [GC (Allocation Failure) 1866K-1066K(5632K), 0.0011751 secs] 2020-08-28T16:37:38.7870800: [GC (Allocation Failure) 2090K-1314K(5632K), 0.0010511 secs] 2020-08-28T16:37:38.7890800: [GC (Allocation Failure) 2338K-1554K(5632K), 0.0009488 secs] 同样在没有内存溢出时候他和强引用是没有区别的 我们把消耗内存的算法改一下让它产生内存溢出 // 消耗大量内存public static void drainMemory() {String[] array new String[1024 * 1000];for(int i 0; i 1024 * 10; i) {for(int j a; j b; j) {array[i] (char)j;}}} 再重新跑一下 2020-08-28T16:39:38.3100800: [GC (Allocation Failure) 1024K-624K(5632K), 0.0012934 secs] 2020-08-28T16:39:38.3510800: [GC (Allocation Failure) 1641K-884K(5632K), 0.0011559 secs] 2020-08-28T16:39:38.3650800: [GC (Allocation Failure) 1407K-934K(5632K), 0.0011081 secs] 2020-08-28T16:39:38.3660800: [GC (Allocation Failure) 934K-942K(5632K), 0.0007891 secs] 2020-08-28T16:39:38.3670800: [Full GC (Allocation Failure) 942K-706K(5632K), 0.0035185 secs] 2020-08-28T16:39:38.3710800: [GC (Allocation Failure) 706K-706K(5632K), 0.0002779 secs] 2020-08-28T16:39:38.3710800: [Full GC (Allocation Failure) 706K-690K(5632K), 0.0051638 secs]obj [com.example.demo.conf.test$MyOb51fe5ed6] is gc Exception in thread main java.lang.OutOfMemoryError: Java heap spaceat com.example.demo.conf.test.drainMemory(test.java:33)at com.example.demo.conf.test.main(test.java:27) 可以看到再抛出 OOM 之前会先清理掉这个对象强引用 OOM 前如果还是可达的也不会清理掉可以自己试一下 然后看弱引用 public static void main(String[] args) {ReferenceQueueMyOb queue new ReferenceQueue();//创建一个引用给定对象并在给定队列中注册的新的弱引用。WeakReferenceMyOb ob new WeakReference(new MyOb() , queue);drainMemory();Thread.sleep(1000);System.out.println(ob ob.get());System.out.println(queue poll queue.poll());} 记得把之前的调OOM的内存消耗部分修改回来 得到的结果有多种情况 2020-08-28T17:38:16.6250800: [GC (Allocation Failure) 1024K-600K(5632K), 0.0008772 secs] 2020-08-28T17:38:16.6570800: [GC (Allocation Failure) 1624K-839K(5632K), 0.0007530 secs] 2020-08-28T17:38:16.6710800: [GC (Allocation Failure) 1863K-1009K(5632K), 0.0005883 secs]obj [com.example.demo.conf.test$MyOb51fe5ed6] is gc 2020-08-28T17:38:16.6720800: [GC (Allocation Failure) 2033K-1201K(5632K), 0.0006779 secs] 2020-08-28T17:38:16.6740800: [GC (Allocation Failure) 2225K-1353K(5632K), 0.0005505 secs] 2020-08-28T17:38:16.6750800: [GC (Allocation Failure) 2377K-1529K(5632K), 0.0010291 secs] ob null queue poll java.lang.ref.WeakReference270421f5 2020-08-28T17:39:50.2490800: [GC (Allocation Failure) 1024K-592K(5632K), 0.0007809 secs] 2020-08-28T17:39:50.2830800: [GC (Allocation Failure) 1610K-843K(5632K), 0.0029328 secs] 2020-08-28T17:39:50.3040800: [GC (Allocation Failure) 1867K-1045K(5632K), 0.0008099 secs] 2020-08-28T17:39:50.3060800: [GC (Allocation Failure) 2069K-1157K(5632K), 0.0012691 secs] 2020-08-28T17:39:50.3080800: [GC (Allocation Failure) 2181K-1341K(5632K), 0.0009482 secs] 2020-08-28T17:39:50.3130800: [GC (Allocation Failure) 2365K-1485K(5632K), 0.0014565 secs] ob com.example.demo.conf.test$MyOb270421f5 queue poll null 可以发现Young GC 是不一定会回收由系统来判断回收的时机。 然后我们改一下代码改用 System.gc() 触发 FULL GC 看看有什么不同 public static void main(String[] args) {ReferenceQueueMyOb queue new ReferenceQueue();//创建一个引用给定对象并在给定队列中注册的新的弱引用。WeakReferenceMyOb ob new WeakReference(new MyOb() , queue);System.gc();System.out.println(ob ob.get());System.out.println(queue poll queue.poll());} 2020-08-28T18:25:22.9670800: [GC (Allocation Failure) 1024K-632K(5632K), 0.0014284 secs] 2020-08-28T18:25:23.0010800: [GC (Allocation Failure) 1650K-846K(5632K), 0.0008219 secs] 2020-08-28T18:25:23.0160800: [GC (System.gc()) 1370K-886K(5632K), 0.0005198 secs] 2020-08-28T18:25:23.0170800: [Full GC (System.gc()) 886K-707K(5632K), 0.0045606 secs]obj [com.example.demo.conf.test$MyOb51fe5ed6] is gc ob null queue poll null 可以发现 GC 后肯定会取消对象的引用 注意上面的控制台顺序不一定和真实的gc顺序一样关键得看 ob.get() 是否为空去判断 对象的自我救赎 即使在可达性分析算法中判定为不可达的对象也不是“非死不可”的这时候它们暂时还处于“缓刑”阶段要真正宣告一个对象死亡至少要经历两次标记过程如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链那它将会被第一次标记随后进行一次筛选筛选的条件是此对象是否有必要执行finalize()方法。假如对象没有覆盖finalize()方法或者finalize()方法已经被虚拟机调用过那么虚拟机在发生GC的时候只需要判断对象可达 GC Roots 即可判定是否可回收。 如果这个对象被判定为确有必要执行 finalize() 方法那么该对象将会被放置在一个名为 F-Queue 的队列之中并在稍后由一条由虚拟机自动建立的、低调度优先级的 Finalizer 线程去执行它们的 finalize() 方法。这里所说的“执行”是指虚拟机会触发这个方法开始运行但并不承诺一定会等待它运行结束。这样做的原因是如果某个对象的 finalize() 方法执行缓慢或者更极端地发生了死循环将很可能导致 F-Queue 队列中的其他对象永久处于等待甚至导致整个内存回收子系统的崩溃。 finalize() 方法是对象逃脱死亡命运的最后一次机会稍后收集器将对 F-Queue 中的对象进行第二次小规模的标记如果对象要在 finalize() 中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可譬如把自己this关键字赋值给某个类变量或者对象的成员变量那在第二次标记时它将被移出“即将回收”的集合如果对象这时候还没有逃脱那基本上它就真的要被回收了。从代码清单3-2中我们可以看到一个对象的 finalize() 被执行但是它仍然可以存活。 并不鼓励大家使用这个方法来拯救对象。相反笔者建议大家尽量避免使用它因为它并不能等同于C和C语言中的析构函数而是Java刚诞生时为了使传统C、C程序员更容易接受Java所做出的一项妥协。它的运行代价高昂不确定性大无法保证各个对象的调用顺序如今已被官方明确声明为不推荐使用的语法。有些教材中描述它适合做“关闭外部资源”之类的清理性工作这完全是对finalize()方法用途的一种自我安慰。finalize()能做的所有工作使用try-finally或者其他方式都可以做得更好、更及时所以笔者建议大家完全可以忘掉Java语言里面的这个方法。 垃圾回收算法--分代 标记清除算法 步骤很简单 先根据可达性算法标记出相应的可回收对象图中黄色部分对可回收的对象进行回收 优点是不需要额外空间 缺点是两次扫描耗时严重会产生内存碎片 复制算法 把堆等分成两块区域, A 和 B区域 A 负责分配对象区域 B 不分配, 对区域 A 使用以上所说的标记法把存活的对象标记出来然后把区域 A 中存活的对象都复制到区域 B存活对象都依次紧邻排列最后把 A 区对象全部清理掉释放出空间这样就解决了内存碎片的问题了。 不过复制算法的缺点很明显比如给堆分配了 500M 内存结果只有 250M 可用空间平白无故减少了一半这肯定是不能接受的另外每次回收也要把存活对象移动到另一半效率低下我们可以想想删除数组元素再把非删除的元素往一端移效率显然堪忧 标记整理法 前面两步和标记清除法一样不同的是它在标记清除法的基础上添加了一个整理的过程 即将所有的存活对象都往一端移动, 紧邻排列如图示再清理掉另一端的所有区域这样的话就解决了内存碎片的问题。 但是缺点也很明显每进一次垃圾清除都要频繁地移动存活的对象效率十分低下。 垃圾处理器 名称 负责区域 使用算法 描述 Serial young 复制算法 单线程Client默认新生代处理器 ParNew young 复制算法 多线程Serial的多线程版 Parallel Scavenge young 复制算法 多线程注重停顿时间和吞吐量 Serial Old old 标记整理 Client默认老年代处理器Serial的老年版本CMS的后备方案 Parallel Old old 标记整理 多线程注重停顿时间和吞吐量 CMS old 标记清除 整个过程分为4个步骤 初始标记(CMS initial mark) -stop the world并发标记(CMS concurrent mark)重新标记(CMS remark) -stop the world并发清除(CMS concurrent sweep) G1 young/old 整体标记整理 局部复制 多线程内存分区各分区大小相同同一分区逻辑角色相同都是新生代等回收以分区为单位复制到另一个分区首先回收垃圾最多的分区低停顿使用暂停预测模型。
http://www.lakalapos1.cn/news/20677/

相关文章:

  • 洒长春菩网站建设建设局和住建局区别
  • 属于网站建设过程规划服装网站建设可行性分析
  • 投资公司网站建设方案用html制作个人简历
  • 上海网站原型设计哪些网站教做生物实验
  • 宿州网站建设哪家好如何在jsp上做网站页面
  • 网站做app的软件叫什么wordpress去除wordpress新闻
  • 北京学设计去哪个网站好全返利网站建设
  • 本地网站搭建如何访问网页硬件开发能力
  • 凡科网站模板wordpress后台分类目录添加自定义
  • 重庆网站建公司大全工业app开发平台
  • wordpress 站点迁移网站建设企业文化
  • 网站组成元素做非法网站怎么判刑
  • 响应云网站模板下载天津外包加工网
  • 深圳市 交易建设中心网站wordpress社区聊天室
  • 网站建设与规划总结wordpress缓存优化
  • 百度移动网站生成西安做兼职网站设计
  • 怎么免费建设金融网站临沂吧网站建设
  • 怎么上网做网站wordpress动画轮播代码教程
  • 文化礼堂建设情况网站惠州悦商做网站
  • 大连网站代运营的公司有哪些什么平台可以做推广
  • 网站建设的一般步骤大数据培训课程
  • 百度能收录的免费网站上海发布
  • 做化妆品注册和注册的网站吗路由器做网站教程
  • 淘宝网怎样做网站个人域名申请的方法
  • 网站需要前台后台为什么php做不了大网站
  • 汕头h5建站tp5企业网站开发
  • 做物流网站的多少钱自己做的网站放在服务器哪里
  • 网站开发的ppt报告哈尔滨网站优化对策
  • aaaa景区网站建设标准做网站策划书
  • 郑州网站建设哪家好淘宝基地网站怎么做