看看苹果手机清理内存怎么清理有多垃圾!还不如国产机两千元的

电脑主机我拔了下内存条看看型号又插了回去,然后显示器无信号然后怎么检查替换显卡内存条清理,就是无信号急死了。... 电脑主机我拔了下内存条看看型号又插了回去,然后显示器无信号然后怎么检查替换显卡内存条清理,就是无信号急死了。

2016年四川省农业厅先进个人; 资阳市绿色防控推廣工作先进个人;


把显示器串口线也拔了重新插上内存条插槽吹下有没有灰,擦擦金手指

这些都做了还是没有用。

你对这个回答的評价是?


· 知道合伙人数码行家
没有吖换了根还是不行。

你对这个回答的评价是?

你对这个回答的评价是


· TA获得超过1.2万个赞

内存条偠插紧,两边的卡扣要扣好

你对这个回答的评价是?


看看内存条有没有正确插放好

插对得换了根内存条卡槽还是一样

你对这个回答的評价是?

下载百度知道APP抢鲜体验

使用百度知道APP,立即抢鲜体验你的手机镜头里或许有别人想知道的答案。

}

        JVM 是可运行 Java 代码的假想计算机 包括一套字节码指令集、一组寄存器、一个栈、 一个垃圾回收,堆 和 一个存储方法域JVM 是运行在操作系统之上的,它与硬件没有直接 的交互

        我们都知道 Java 源文件,通过编译器能够生产相应的.Class 文件,也就是字节码文件 而字节码文件又通过 Java 虚拟机中的解释器,编译成特定机器仩的机器码 也就是如下:

        每一种平台的解释器是不同的,但是实现的虚拟机是相同的这也就是 Java 为什么能够 跨平台的原因了 ,当一个程序从开始运行这时虚拟机就开始实例化了,多个程序启动就会 存在多个虚拟机实例程序退出或者关闭,则虚拟机实例消亡多个虚拟機实例之间数据不 能共享。

冲区分配、同步对象、栈、程序计数器等准备好以后就会创建一个操作系统原生线程。 Java 线程结束原生线程隨之被回收。操作系统负责调度所有线程并把它们分配到任何可 用的 CPU 上。当原生线程初始化完毕就会调用 Java 线程的 run() 方法。当线程结束时会释放原生线程和 Java 线程的所有资源。

Hotspot JVM 后台运行的系统线程主要有下面几个:

DirectByteBuffer 对象作为这块内存的引用进行操作(详见: Java I/O 扩展), 这样就避免了在 Java 堆和 Native 堆中来回复制数据, 因此在一些场景中可以显著提高性能

        一块较小的内存空间, 是当前线程所执行的字节码的行号指示器,每条线程都偠有一个独立的 程序计数器这类内存也称为“线程私有”的内存。 

用于存储局部变量表、操作数栈、动态链接、方法出口等信息每一個方法从调用直至执行完成 的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程

Exception)。栈帧随着方法调用而创建随着方法结束而銷毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异 常)都算作方法结束。

那么该栈将会是一个 C 栈但 HotSpot VM 直接就把本哋方法栈和虚拟机栈合二为一。

HotSpot 的垃圾收集器就可以像管理 Java 堆一样管理这部分内存,  而不必为方法区开发专门的内存管理器(永久带的内存回收的主要目标是针对常量池的回收和类型 的卸载, 因此收益一般很小) 

Table),用于存放编译期生成的各种字面量和符号引用这部分内容将在類加 载后存放到方法区的运行时常量池中。 Java 虚拟机对 Class 文件的每一部分(自然也包括常量 池)的格式都有严格的规定每一个字节用于存储哪种数据都必须符合规范上的要求,这样才会 被虚拟机认可、装载和执行

    首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年 龄鉯及达到了老年的标准则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不 够位置了就放到老年区);

        老年代的对象比较稳定所以 MajorGC 鈈会频繁执行。在进行 MajorGC 前一般都先进行 了一次 MinorGC使得有新生代的对象晋身入老年代,导致空间不够用时才触发当无法找到足 够大的连续涳间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。 

少内存损耗我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的 时候就会抛出 OOM(Out of Memory)异常。

        指内存的永久保存区域主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被 放叺永久区域,它和和存放实例的区域不同,GC 不会在主程序运行期对永久区域进行清理所以这 也导致了永久代的区域会随着加载的 Class 的增多而脹满,最终抛出 OOM 异常

     在 Java8 中,永久代已经被移除被一个称为“元数据区”(元空间)的区域所取代。元空间 的本质和永久代类似元空間与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用 本地内存因此,默认情况下元空间的大小仅受本地内存限制。类嘚元数据放入 native  memory, 字符串池和类的静态变量放入 java 堆中这样可以加载多少类的元数据就不再由 MaxPermSize 控制, 而由系统的实际可用空间来控制。

            在 Java 中引鼡和对象是有关联的。如果要操作对象则必须用引用进行因此,很显然一个简单 的办法是通过引用计数来判断一个对象是否可以回收簡单说,即一个对象如果没有任何与之关 联的引用即他们的引用计数都不为 0,则说明对象不太可能再被用到那么这个对象就是可回收 對象。

roots”和一个对象之间没有可达路径则称该对象是不可达的。要注意的是不可达对象不等价于可回收对象,不可达对象变为可回收對象至少要经过两次标记 过程两次标记后仍然是可回收对象,则将面临回收

        最基础的垃圾回收算法,分为两个阶段标注和清除。标記阶段标记出所有需要回收的对象清 除阶段回收被标记的对象所占用的空间。如图

        从图中我们就可以发现该算法最大的问题是内存碎爿化严重,后续可能发生大对象不能找到可 利用空间的问题

        为了解决 Mark-Sweep 算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小 的两块每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去把已使用 的内存清掉,如图:

        这种算法虽然實现简单内存效率高,不易产生碎片但是最大的问题是可用内存被压缩到了原 本的一半。且存活对象增多的话Copying 算法的效率会大大降低。

        结合了以上两个算法为了避免缺陷而提出。标记阶段和 Mark-Sweep 算法相同标记后不是清 理对象,而是将存活对象移向内存的一端然后清除端边界外的对象。如图:

 Generation)老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃 圾回收时都有大量垃圾需偠被回收因此可以根据不同区域选择不同的算法。

Space, To Space)每次使用 Eden 空间和其中的一块 Survivor 空间,当进行回收时将该两块空间中还存活的对象复淛到另 一块 Survivor 空间中。

1.4.5.2. 老年代与标记复制算法

而老年代因为每次只回收少量对象因而采用 Mark-Compact 算法。

1. JAVA 虚拟机提到过的处于方法区的永生代(Permanet Generation)它鼡来存储 class 类, 常量方法描述等。对永生代的回收主要包括废弃常量和无用的类 

4. 如果 To Space 无法足够存储某个对象,则将这个对象存储到老生玳

6. 当对象在 Survivor 区躲过一次 GC 后,其年龄就会+1默认情况下年龄到达 15 的对象会被 移到老生代中。

    在 Java 中最常见的就是强引用把一个对象赋给一個引用变量,这个引用变量就是一个强引 用当一个对象被强引用变量引用时,它处于可达状态它是不可能被垃圾回收机制回收的,即 使该对象以后永远都不会被用到 JVM 也不会回收因此强引用是造成 Java 内存泄漏的主要原因之 一。

    软引用需要用 SoftReference 类来实现对于只有软引用的对潒来说,当系统内存足够时它 不会被回收当系统内存空间不足时它会被回收。软引用通常用在对内存敏感的程序中

    弱引用需要用 WeakReference 类来實现,它比软引用的生存期更短对于只有弱引用的对象 来说,只要垃圾回收机制一运行不管 JVM 的内存空间是否足够,总会回收该对象占鼡的内存

    虚引用需要 PhantomReference 类来实现,它不能单独使用必须和引用队列联合使用。虚 引用的主要作用是跟踪对象被垃圾回收的状态

    当前主鋶 VM 垃圾收集都采用”分代收集”(Generational Collection)算法, 这种算法会根据 对象存活周期的不同将内存划分为几块, 如 JVM 中的 新生代、老年代、永久代,这样就可以根据 各年代特点分别采用最适当的 GC 算法

    分区算法则将整个堆空间划分为连续的不同小区间, 每个小区间独立使用, 独立回收. 这样做的 好处是可鉯控制一次回收多少个小区间 , 根据目标停顿时间, 每次合理地回收若干个小区间(而不是 整个堆), 从而减少一次

    Java 堆内存被划分为新生代和年老代兩部分新生代主要使用复制和标记-清除垃圾回收算法; 年老代主要使用标记-整理垃圾回收算法,因此 java 虚拟中针对新生代和年老代分别提供了多种不 同的垃圾收集器JDK1.6 中 Sun HotSpot 虚拟机的垃圾收集器如下:

    Serial(英文连续)是最基本垃圾收集器,使用复制算法曾经是JDK1.3.1 之前新生代唯一的垃圾 收集器。Serial 是一个单线程的收集器它不但只会使用一个 CPU 或一条线程去完成垃圾收集工 作,并且在进行垃圾收集的同时必须暂停其他所有的工作线程,直到垃圾收集结束 Serial 垃圾收集器虽然在收集垃圾过程中需要暂停所有其他的工作线程,但是它简单高效对于限 定单个 CPU 環境来说,没有线程交互的开销可以获得最高的单线程垃圾收集效率,因此 Serial 垃圾收集器依然是 java 虚拟机运行在 Client 模式下默认的新生代垃圾收集器

    ParNew 垃圾收集器其实是 Serial 收集器的多线程版本,也使用复制算法除了使用多线程进行垃 圾收集之外,其余的行为和 Serial 收集器完全一样ParNew 垃圾收集器在垃圾收集过程中同样也 要暂停所有其他的工作线程。ParNew 收集器默认开启和 CPU 数目相同的线程数可以通过-XX:ParallelGCThreads 参数来限 制垃圾收集器的線程数。【Parallel:平行的】 ParNew虽然是除了多线程外和Serial 收集器几乎完全一样但是ParNew垃圾收集器是多 java 虚拟机运行在 Server 模式下新生代的默认垃圾收集器。

    Parallel Scavenge 收集器也是一个新生代垃圾收集器同样使用复制算法,也是一个多线程的垃 圾收集器它重点关注的是程序达到一个可控制的吞吐量(Thoughput,CPU 用于运行用户代码 的时间/CPU 总消耗时间即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)), 高吞吐量可以最高效率地利用 CPU 時间尽快地完成程序的运算任务,主要适用于在后台运算而 不需要太多交互的任务自适应调节策略也是 ParallelScavenge 收集器与 ParNew 收集器的一个 重要区別。

吐量优先的垃圾收集器如果系统对吞吐量要求比较高,可以优先考虑新生代

    Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器其最主要目标是获取朂短垃圾 回收停顿时间,和其他年老代使用标记-整理算法不同它使用多线程的标记-清除算法。 最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验 CMS 工作机制相比其他的垃圾收集器来说更复杂,整个过程分为以下 4 个阶段:

        为了修正在并发标记期间因用户程序繼续运行而导致标记产生变动的那一部分对象的标记 记录,仍然需要暂停所有的工作线程

        清除 GC Roots 不可达对象,和用户线程一起工作不需偠暂停工作线程。由于耗时最长的并 发标记和并发清除过程中垃圾收集线程可以和用户现在一起并发工作,所以总体上来看 CMS 收集器的内存回收和用户线程是一起并发地执行 

1. 基于标记-整理算法,不产生内存碎片

2. 可以非常精确控制停顿时间,在不牺牲吞吐量前提下实现低停顿垃圾回收。 

G1 收集器避免全区域垃圾收集它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域 的垃圾收集进度同时在後台维护一个优先级列表,每次根据所允许的收集时间优先回收垃圾 最多的区域。区域划分和优先级区域回收机制确保 G1 收集器可以在囿限时间获得最高的垃圾收 集效率。

        最传统的一种 IO 模型即在读写数据过程中会发生阻塞现象。当用户线程发出 IO 请求之后内 核会去查看數据是否就绪,如果没有就绪就会等待数据就绪而用户线程就会处于阻塞状态,用 户线程交出 CPU当数据就绪之后,内核会将数据拷贝到鼡户线程并返回结果给用户线程,用户线程才解除 block 状态典型的阻塞 IO 模型的例子为:data = socket.read();如果数据没有就 绪,就会一直阻塞在 read 方法

        当用户线程发起一个 read 操作后并不需要等待,而是马上就得到了一个结果如果结果是一个 error 时,它就知道数据还没有准备好于是它可以再次发送 read 操作。一旦内核中的数据准备 好了并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程然后返回。 所以事实上在非阻塞 IO 模型中,用户线程需要不断地询问内核数据是否就绪也就说非阻塞 IO 不会交出 CPU,而会一直占用 CPU典型的非阻塞 IO 模型一般如下:

囸调用实际的 IO 读写操作。因为在多路复用 IO 模型中只需要使用一个线程就可以管理多个 socket,系统不需要建立新的进程或者线程也不必维护這些线程和进程,并且只有在真正有 socket 读写事件进行时才会使用 IO 资源,所以它大大减少了资源占用在 Java NIO 中,是通 过 selector.select()去查询每个通道是否有箌达事件如果没有事件,则一直阻塞在那里因此这 种方式会导致用户线程的阻塞。多路复用 IO 模式通过一个线程就可以管理多个 socket,只囿当 socket 真正有读写事件发生才会占用资源来进行实际的读写操作因此,多路复用 IO 比较适合连 接数比较多的情况

        另外多路复用 IO 为何比非阻塞 IO 模型的效率高是因为在非阻塞 IO 中,不断地询问 socket 状态 时通过用户线程去进行的而在多路复用 IO 中,轮询每个 socket 状态是内核在进行的这个效 率要比用户线程要高的多。

        不过要注意的是多路复用 IO 模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件 逐一进行响应洇此对于多路复用 IO 模型来说,一旦事件响应体很大那么就会导致后续的事件 迟迟得不到处理,并且会影响新的事件轮询

        在信号驱动 IO 模型中,当用户线程发起一个 IO 请求操作会给对应的 socket 注册一个信号函 数,然后用户线程会继续执行当内核数据就绪时会发送一个信号给用戶线程,用户线程接收到 信号之后便在信号函数中调用 IO

      异步 IO 模型才是最理想的 IO 模型,在异步 IO 模型中当用户线程发起 read 操作之后,立刻就 鈳以开始去做其它的事而另一方面,从内核的角度当它受到一个 asynchronous read 之后, 它会立刻返回说明 read 请求已经成功发起了,因此不会对用户线程产生任何 block然后,内 核会等待数据准备完成然后将数据拷贝到用户线程,当这一切都完成之后内核会给用户线程 发送一个信号,告訴它 read 操作完成了也就说用户线程完全不需要实际的整个 IO 操作是如何 进行的,只需要先发起一个请求当接收内核返回的成功信号时表示 IO 操作已经完成,可以直接

    也就说在异步 IO 模型中IO 操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完 成然后发送一个信號告知用户线程操作已完成。用户线程中不需要再次调用 IO 函数进行具体的 读写这点是和信号驱动模型有所不同的,在信号驱动模型中當用户线程接收到信号表示数据 已经就绪,然后需要用户线程调用 IO 函数进行实际的读写操作;而在异步 IO 模型中收到信号 表示 IO 操作已经完荿,不需要再在用户线程中调用 IO 函数进行实际的读写操作

中,或者从缓冲区写入到通道中Selector(选择区)用于监听多个通道的事件(比如:连接打开, 数据到达)因此,单个线程可以监听多个数据通道

NIO 和传统 IO 之间第一个最大的区别是,IO 是面向流的NIO 是面向缓冲区的。

        Java IO 面向流意味着每次从流中读一个或多个字节直至读取所有字节,它们没有被缓存在任何 地方此外,它不能前后移动流中的数据如果需要前後移动从流中读取的数据,需要先将它缓 存到一个缓冲区NIO 的缓冲导向方法不同。数据读取到一个它稍后处理的缓冲区需要时可在 缓冲區中前后移动。这就增加了处理过程中的灵活性但是,还需要检查是否该缓冲区中包含所 有您需要处理的数据而且,需确保当更多的數据读入缓冲区时不要覆盖缓冲区里尚未处理的 数据。

        IO 的各种流是阻塞的这意味着,当一个线程调用 read() 或 write()时该线程被阻塞,直到有 一些数据被读取或数据完全写入。该线程在此期间不能再干任何事情了 NIO 的非阻塞模式, 使一个线程从某通道发送请求读取数据但是它僅能得到目前可用的数据,如果目前没有数据可 用时就什么都不会获取。而不是保持线程阻塞所以直至数据变的可以读取之前,该线程可以 继续做其他的事情 非阻塞写也是如此。一个线程请求写入一些数据到某通道但不需要等待它 完全写入,这个线程同时可以去做別的事情 线程通常将非阻塞 IO 的空闲时间用于在其它通道上 执行 IO 操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)

OutputStream,而 Channel 昰双向 的既可以用来进行读操作,又可以用来进行写操作

        上面的图描述了从一个客户端向服务端发送数据,然后服务端接收数据的过程客户端发送 数据时,必须先将数据存入 Buffer 中然后将 Buffer 中的内容写入通道。服务端这边接收数据必 须通过 Channel 将数据读入到 Buffer 中然后再从 Buffer 中取絀数据来处理。

件发生便获取事件然后针对每个事件进行相应的响应处理。这样一来只是用一个单线程就可 以管理多个通道,也就是管理多个连接这样使得只有在连接真正有读写事件发生时,才会调用 函数来进行读写就大大地减少了系统开销,并且不必为每个连接嘟创建一个线程不用去维护 多个线程,并且避免了多线程之间的上下文切换导致的开销

    JVM 类加载机制分为五个部分:加载,验证准备,解析初始化,下面我们就分别来看一下这 五个过程

文件获取,这里既 可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取)也可以在运行时计算生成(动态代理), 也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类)

        准备阶段是正式为类变量分配内存并设置类变量的初始值階段,即在方法区中分配这些变量所使 用的内存空间注意这里所说的初始值概念,比如一个类变量定义为:

实际上变量 v 在准备阶段过后嘚初始值为 0 而不是 8080将 v 赋值为 8080 的 put static 指令是 程序被编译后,存放于类构造器<client>方法之中

? 符号引用与虚拟机实现的布局无关,引用的目标并不┅定要已经加载到内存中各种虚拟 机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的因为符号引 用的字面量形式明确定义在 Java 虚拟机规范的 Class 文件格式中

? 直接引用可以是指向目标的指针相对偏移量或是一个能间接定位到目标的句柄。如果有 了矗接引用那引用的目标必定已经在内存中存在。 

初始化阶段是类加载最后一个阶段前面的类加载阶段之后,除了在加载阶段可以自定義类加载 器以外其它操作都由 JVM 主导。到了初始阶段才开始真正执行类中定义的 Java 程序代码。 

初始化阶段是执行类构造器<client>方法的过程<client>方法是由编译器自动收集类中的类变 量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证子<client>方法执行之前父类 的<client>方法已经执行唍毕,如果一个类中没有对静态变量赋值也没有静态语句块那么编译

注意以下几种情况不会执行类初始化:

实现自定义的类加载器。

    当┅个类收到了类加载请求他首先不会尝试自己去加载这个类,而是把这个请求委派给父 类去完成每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中 只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加載的 Class),子类加载器才会尝试自己去加载 采用双亲委派的一个好处是比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载 器加载这个类最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载 器最终得到的都是同样一个 Object 对象

    OSGi 服务平台提供在多种网络设备上无需重启的动态改变构造的功能为了最小化耦合度和促使 这些耦合度可管理,OSGi 技术提供一种面向服务的架构它能使这些组件动态地发现對方。

    OSGi 旨在为实现 Java 程序的模块化编程提供基础条件基于 OSGi 的程序很可能可以实现模块级 的热插拔功能,当程序升级更新时可以只停用、偅新安装然后启动程序的其中一部分,这对企 业级程序开发来说是非常具有诱惑力的特性

    OSGi 描绘了一个很美好的模块化开发目标,而且定義了实现这个目标的所需要服务与架构同时 也有成熟的框架进行实现支持。但并非所有的应用都适合采用 OSGi 作为基础架构它在提供强大 功能同时,也引入了额外的复杂度因为它不遵守了类加载的双亲委托模型。

}

JVM调优是每个高级程序员的必修课在本章中,我会从发展过程以及核心价值来剖析JVM的体系结构为了让大家更好的理解JVM的工作机制,
我会在讲解完运行时数据区之后再通过一个类的加载过程到这个类最终在运行时数据区中的存储来更进一步理解JVM的工作原理。最后通过对内存的回收机制和垃圾回收算法嘚讲解,引出到JVM的性能调优这一主题在这个部分会着重讲解垃圾回收算法以及常见的垃圾回收器的区别和使用场景。

程序计数器(线程私有)

程序计数器(Program Counter Register)也有称作为 PC 寄存器。保存的是程序当 前执行的指令的地址(也可以说保存下一条指令的所在存储单元的地址)當 CPU 需要执 行指令时,需要从程序计数器中得到当前需要执行的指令所在存储单元的地址然后根据得 到的地址获取到指令,在得到指令之後程序计数器便自动加 1 或者根据转移指针得到下 一条指令的地址,如此循环直至执行完所有的指令。也就是说是用来指示执行哪条指囹的

Java 栈中存放的是一个个的栈帧,每个栈帧对应一个被调用的方法在栈帧中包括局 部变量表、操作数栈、指向当前方法所属的类的运荇时常量池的引用、方法返回地址、额 外的附加信息。当线程执行一个方法时就会随之创建一个对应的栈帧,并将建立的栈帧压 栈当方法执行完毕之后,便会将栈帧出栈因此可知,线程当前执行的方法所对应的栈帧 必定位于 Java 栈的顶部

本地方法栈与 Java 栈的作用和原理非瑺相似。区别只不过是 Java 栈是为执行 Java 方法服务的而本地方法栈则是为执行本地方法(Native Method)服务的。在 JVM 规 范中并没有对本地方发展的具体实現方法以及数据结构作强制规定,虚拟机可以自由实现 它在 HotSopt 虚拟机中直接就把本地方法栈和 Java 栈合二为一。

Java 中的堆是用来存储对象本身的鉯及数组(当然数组引用是存放在 Java 栈中的), 堆是被所有线程共享的在 JVM 中只有一个堆。所有对象实例以及数组都要在堆上分配内 存單随着 JIT 发展,栈上分配标量替换优化技术,在堆上分配变得不那么到绝对只能 在 server 模式下才能启用逃逸分析。

方法区中存储了每个类嘚信息(包括类的名称、方法信息、字段信息)、静态变 量、常量以及编译器编译后的代码等。 在 Class 文件中除了类的字段、方法、接口等描述信息外还有一项信息是常量池, 用来存储编译期间生成的字面量和符号引用

直接分配在物理内存中,并不占用堆空间其可申请的朂大内存受操作系统 限制

各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码(ByteCode)是 构成平台无关性的基石,也是语訁无关性的基础Java 虚拟机不和包括 Java 在内的任何语 言绑定,它只与“Class 文件”这种特定的二进制文件格式所关联Class 文件中包含了 Java 虚拟机指令集囷符号表以及若干其他辅助信息。

Java 跨平台的基础

各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码(ByteCode)是 构成平台無关性的基石也是语言无关性的基础。Java 虚拟机不和包括 Java 在内的任何语 言绑定它只与“Class 文件”这种特定的二进制文件格式所关联,Class 文件Φ包含了 Java 虚拟机指令集和符号表以及若干其他辅助信息

任何一个 Class 文件都对应着唯一一个类或接口的定义信息,但反过来说Class 文件实际 上咜并不一定以磁盘文件的形式存在。 Class 文件是一组以 8 位字节为基础单位的二进制流

Java 虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字(称为操作码, Opcode)以及跟随其后的零至多个代表此操作所需参数(称为操作数Operands)而构成。 由于限制了 Java 虚拟机操作码的长度为┅个字节(即 0~255)这意味着指令集的操作 码总数不可能超过 256 条。
大多数的指令都包含了其操作所对应的数据类型信息例如: iload指令用于從局部变量表中加载int型的数据到操作数栈中,而fload指令加载的则是float 类型的数据
大部分的指令都没有支持整数类型 byte、char 和 short,甚至没有任何指令支持 boolean 类 型大多数对于 boolean、byte、short 和 char 类型数据的操作,实际上都是使用相应的 int 类型作为运算类型

类从被加载到虚拟机内存中开始到卸载出内存為止,它的整个生命周期包括:加载 (Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化 (Initialization)、使用(Using)和卸载(Unloading)7 个阶段其中验证、准备、解析 3 个部分统称为连接(Linking) 于初始化阶段,虚拟机规范则是严格规定了有且只有 5 种情况必须立即对类进行“初始化” (而加载、验证、准备自然需要在此之前开始)

垃圾回收器和内存分配策略

Java 中是值传递还是引用传递

在运行栈中,基本类型和引用的处理是一样的都是傳 值,所以如果是传引用的方法调用,也同时可以理解为“传引用值”的传值调用即引用的 处理跟基本类型是完全一样的。但是当进叺被调用方法时被传递的这个引用的值,被程序 解释(或者查找)到堆中的对象这个时候才对应到真正的对象。如果此时进行修改修 改的是引用对应的对象,而不是引用本身即:修改的是堆中的数据。所以这个修改是可以 对象从某种意义上说,是由基本类型组成嘚可以把一个对象看作为一棵树,对象的属性 如果还是对象则还是一颗树(即非叶子节点),基本类型则为树的叶子节点程序参数傳 递时,被传递的值本身都是不能进行修改的但是,如果这个值是一个非叶子节点(即一个 对象引用)则可以修改这个节点下面的所囿内容。

对象引用类型分为强引用、软引用、弱引用和虚引用 强引用:就是我们一般声明对象是时虚拟机生成的引用,强引用环境下垃圾回收时需要严 格判断当前对象是否被强引用,如果被强引用则不会被垃圾回收

软引用软引用一般被做为缓存来使用。与强引用的区别昰软引用在垃圾回收时,虚拟机 会根据当前系统的剩余内存来决定是否对软引用进行回收如果剩余内存比较紧张,则虚拟 机会回收软引用所引用的空间;如果剩余内存相对富裕则不会进行回收。换句话说虚拟 机在发生 OutOfMemory 时,肯定是没有软引用存在的

弱引用弱引用与軟引用类似,都是作为缓存来使用但与软引用不同,弱引用在进行垃圾 回收时是一定会被回收掉的,因此其生命周期只存在于一个垃圾回收周期内 强引用不用说,我们系统一般在使用时都是用的强引用而“软引用”和“弱引用”比较少见。 他们一般被作为缓存使用而且一般是在内存大小比较受限的情况下做为缓存。因为如果内 存足够大的话可以直接使用强引用作为缓存即可,同时可控性更高洇而,他们常见的是 被使用在桌面应用系统的缓存

比较古老的回收算法。原理是此对象有一个引用即增加一个计数,删除一个引用则減少一 个计数垃圾回收时,只用收集计数为 0 的对象此算法最致命的是无法处理循环引用的 问题。

此算法执行分两阶段第一阶段从引鼡根节点开始标记所有被 引用的对象,第二阶段遍历整个堆把未标记的对象清除。此算法需要暂停整个应用同时, 会产生内存碎片

此算法把内存空间划为两个相等的区域每次只使用其中一个区域。垃 圾回收时遍历当前使用区域,把正在使用中的对象复制到另外一个區域中次算法每次只 处理正在使用中的对象,因此复制成本比较小同时复制过去以后还能进行相应的内存整理, 不会出现“碎片”问題当然,此算法的缺点也是很明显的就是需要两倍内存空间。

此算法结合了“标记-清除”和“复制”两个算法的优点也是分 两阶段,第一阶段从根节点开始标记所有被引用对象第二阶段遍历整个堆,清除标记对 象并未标记对象并且把存活对象“压缩”到堆的其中┅块,按顺序排放此算法避免了“标 记-清除”的碎片问题,同时也避免了“复制”算法的空间问题

一个 web 应用不是一个孤立的个体,它昰一个系统的部分系统中的每一部分都会影响整 个系统的性能

常用的性能评价/测试指标

提交请求和返回该请求的响应之间使用的时间,┅般比较关注平均响应时间 常用操作的响应时间列表:

同一时刻,对服务器有实际交互的请求数 和网站在线用户数的关联:1000 个同时在線用户数,可以估计并发数在 5%到 15%之间 也就是同时并发数在 50~150 之间。

对单位时间内完成的工作量(请求)的量度

系统吞吐量和系统并发数以及响應时间的关系: 理解为高速公路的通行状况: 吞吐量是每天通过收费站的车辆数目(可以换算成收费站收取的高速费) 并发数是高速公蕗上的正在行驶的车辆数目, 响应时间是车速 车辆很少时,车速很快但是收到的高速费也相应较少;随着高速公路上车辆数目的增多, 车速略受影响但是收到的高速费增加很快; 随着车辆的继续增加,车速变得越来越慢高速公路越来越堵,收费不增反降; 如果车流量继续增加超过某个极限后,任务偶然因素都会导致高速全部瘫痪车走不动, 当然后也收不着而高速公路成了停车场(资源耗尽)。

不应该把大量的时间耗费在小的性能改进上过早考虑优化是所有噩梦的根源。 所以我们应该编写清晰,直接易读和易理解的代码,真正的优化应该留到以后等到性 能分析表明优化措施有巨大的收益时再进行。

所有的性能调优都有应该建立在性能测试的基础上,矗觉很重要但是要用数据说话,可 以推测但是要通过测试求证。

寻找系统瓶颈分而治之,逐步优化

性能测试后对整个请求经历的各个环节进行分析,排查出现性能瓶颈的地方定位问题, 分析影响性能的的主要因素是什么内存、磁盘 IO、网络、CPU,还是代码问题架構设 计不足?或者确实是系统资源不足

由于文章篇幅原因,更多的细节知识点已经写不完了我全部总结在下面这份【JVM与性能调优知识點】里面了,各位需要的话可以关注我的公众号前程有光免费领取

欢迎关注公众号:前程有光领取这份【JVM与性能调优知识点】+一线大厂Java媔试题总结+各知识点学习思维导+一份300页pdf文档的Java核心知识点总结!

}

我要回帖

更多关于 苹果手机清理内存怎么清理 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信