首页 > 免root版 > gg修改器root失败怎么办_gg修改器为什么用不了Root请教学
gg修改器root失败怎么办_gg修改器为什么用不了Root请教学
  • gg修改器root失败怎么办_gg修改器为什么用不了Root请教学

  • 大小:15.13MB日期:2024-05-08 10:53:00
  • 语言:简体中文系统:Android
绿色无毒,安全可靠!部分设备误报拦截请通过!

应用详情

大家好,今天小编为大家分享关于gg修改器root失败怎么办_gg修改器为什么用不了Root请教学的内容,赶快来一起来看看吧。

JVM是什么?

JVM全称Java Virtual Machine,也就是我们说的Java虚拟机。它是用于编译Java文件的编译器

Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。

运行时数据区域

由上图,我们可以看到Java虚拟机在它所管理的内存中,根据功能不同,将运行时数据区分为了5块。下面就它们简单的介绍下

程序计数器

它是一块较小的内存空间。在虚拟机概念模型里,字节码解释器通过改变它的值来选取下一条需要执行的字节码指令。分支循环等基础功能都需要依靠它来执行。

Java并发编程中,由于其是依托于时间片轮询的方式实现的。在任一确定时间里,一个处理器只能执行一条字节码指令,所以该内存空间在线程之间是不共享的。并且由于其存储的数据所占空间的大小不会随程序的执行而发生改变,所以此区域不会出现OutOfMemoryError的情况。

虚拟机栈

它在线程之间也是不共享的。它是用于描述Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。

在虚拟机规范中,对此区域规定了两种异常。

  1. StackOverflowError
  2. 当前请求的栈深度大于虚拟机所允许的深度时抛出。
  3. OutOfMemoryError
  4. 根据虚拟机的实现不同,可能存在固定长度的虚拟机栈,而针对这种虚拟机栈,一旦拓展时无法申请到足够的内存,就会抛出该异常。

局部变量表

它是存放在编译期可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型),它不等同于对象本身,根据不同的虚拟机实现,它可能是一个指向对象起始地址的引用指针,也可能指向一个代表对象的句柄或者其他与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。

它的内存空间在编译期就已完成分配。当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是完全确定的,运行期间,该空间不会更改。

本地方法栈

它的特点和功能与虚拟机栈基本一致。唯一的不同点在于本地方法栈描述Native方法的,而虚拟机栈描述Java方法的。因此,甚至有的虚拟机直接将二者合并了。

它是所有线程共享的一块内存区域,随着虚拟机启动而启动。它的作用只有一个——存放对象实例,所以在几乎所有应用中,它所占的内存区域是最大的。它是垃圾收集器最主要的管理区域。在堆中,根据垃圾收集器的算法——分代收集算法。我们又将堆分为:初生代,老年代。这里先不展开讨论这几代的细节,在垃圾回收中再详细讨论。当虚拟机无法继续为它扩展内存空间时,会抛出OutOfMemoryError。

方法区

它同样也是所有线程共享的内存区域。它用于存储已被虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码等数据。通常我们更习惯将它称为“永久代(JDK1.8之后,改为了元空间)”。当虚拟机无法继续为它扩展内存空间时,会抛出OutOfMemoryError。

运行时常量池

在方法区中,有一个特别的存在——运行时常量池。由于Java程序的运行过程中,不仅会使用一些存储在Class文件上的常量池,更可能随着程序的运行,产生新的常量(我们最常用到的便是Stringintern()方法)。所以在这过程中,会将使用到的常量再次存储,而存储的地方即为——运行时常量池

垃圾回收

在Java虚拟机中,针对垃圾回收,所使用的算法为可达性分析算法

可达性分析算法

这种算法会选择一些对象作为”GC Roots”。以这些被选为”GC Roots”的对象作为起始点,向下搜索,这些走过的路径被我们称为引用链。当一个对象到达”GC Roots”间没有任何引用链时,则说明该对象不可用。而在Java中,GC Root的对象主要有以下几种:

  1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  2. 方法区中类静态属性引用的对象。
  3. 方法区中常量引用的对象。
  4. 本地方法栈中native方法引用的对象。

收什么?

正如它的名称,垃圾回收收的就是”垃圾”——无用的对象。在Java中,一个对象是否有用,关键得看其”引用”——如果reference类型的数据中存储的数值代表的是另一块内存的起始地址,则称这块内存为一个引用。一个对象若被另一个对象所引用,即为有用的对象;反之,则为无用的对象。我们通常根据强度,将其分为4种:

  1. 强引用
  2. 它是指在程序代码中普遍存在的一种应用,形似于”Object o = new Object()”这种。只要它还存在,垃圾回收器就永远不做回收。
  3. 软引用
  4. 它被用来描述一些还有用但并非必须的对象。这些对象会在系统将发生内存溢出前,被列入回收范围之中。当进行第二次回收时,还是没有足够内存,虚拟机才会抛出内存溢出异常。
  5. 弱引用
  6. 它也是用来描述非必需对象,但与软引用不同,它相对更一些。这些对象只会活到下一次垃圾回收发生之前。当垃圾收集器工作时,无论内存是否足够,这些对象都会被回收
  7. 虚引用
  8. 它也称为幽灵引用或幻影引用。在这4种引用中,它的强度最弱。

怎么收?

垃圾收集器在通过可达性分析算法判断一个对象不可达时。并不会直接开始它的回收工作,而是将该对象放入一个称为F-Queue的队列中。在这个队列中的所有对象,会在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去执行对象上的finalize()方法(但并不一定保证执行完),然后被垃圾收集器第二次标记(如果在finalize()方法中重新被引用,则不会标记)。这些被第二次标记了的对象,才会被回收

下面谈谈各代分别使用什么算法来做回收的吧。

初生代

由于初生代的特点——每次垃圾回收都有大批对象死去,能活下来的只有少部分。所以在堆中,又将初生代被分为了3块内存区域:Eden、From Survivor、To Survivor。它们的所占内存比例为8:1:1EdenFrom Survivor用于存储对象,当回收发生时,将这两块区域中还存活着的对象一次性的复制到To Survivor区中,再清理掉EdenFrom Survivor这两块区域上的对象。这也就是垃圾回收的一种算法——复制算法

但To Survivor的容量不足以存储下存活下来的所有对象,这种极端情况显然也是存在的。这里就得介绍下分配担保机制了,本文暂不做展开,有兴趣可以自行了解(主要是怕扯得太长,文章存储不下)。

老年代

对象进入老年代后,一般都会存活很长一段时间。针对老年代的特点,如果在选用复制算法,就显然不够合理了(它会牺牲掉一定的存储空间)。所以在老年代上,虚拟机一般使用标记-清除算法标记-整理算法。下面就两种算法,做简单的分析。

标记-清除算法

顾名思义,它分为了”标记”和”清除”两个阶段:首先标记出所有需要回收的对象,再统一回收。

根据上图,我们其实可以看到经过标记-清除算法回收后的内存空间,并不连续。这样就导致了一个问题,当我们需要分配较大对象时,无法获得一个足够的内存空间,为此虚拟机不得不再触发一次垃圾回收。

标记-整理算法

它其实跟标记-清除算法原理差不多。区别在于,它在清除前做了一个处理——将所有存活对象统一向一端移动,然后直接清除边界以外的内存空间。

永久代(方法区或元空间)

在永久代中,一般的理解是其不做回收。其实不然,垃圾收集器仍会回收永久代中内存。只不过在这里的回收,和以上有点不同,这里回收的”性价比”比较低:在其它代中,尤其初生代,一般会回收70%-95%的内存空间,而在永久代中回收的内存空间远低于此。

永久代中,一般回收两部分:废弃常量和无用的类。常量一旦未被使用,就会被回收。而类则不同,一般”无用”的类得满足三个条件:

  1. 堆中不存在该类的实例。
  2. 它的ClassLoader已被回收。
  3. 它的Class对象无引用,无法通过反射访问该类的方法。

以上就是关于gg修改器root失败怎么办_gg修改器为什么用不了Root请教学的全部内容,感谢大家的浏览观看,如果你喜欢本站的文章可以CTRL+D收藏哦。

相关文章

热门下载

大家还在搜