您的位置:首页 > 新闻 > 热点要闻 > 自己怎么搞个软件出来_优化关键词的步骤_温州seo网站建设_网络广告创意

自己怎么搞个软件出来_优化关键词的步骤_温州seo网站建设_网络广告创意

2025/4/18 5:30:36 来源:https://blog.csdn.net/2302_78527593/article/details/146870879  浏览:    关键词:自己怎么搞个软件出来_优化关键词的步骤_温州seo网站建设_网络广告创意
自己怎么搞个软件出来_优化关键词的步骤_温州seo网站建设_网络广告创意

一.JVM概述

1.JVM的作用

把字节码编译为机器码去执行,负责把字节码装载到虚拟机中

现在的 JVM 不仅可以执行 java 字节码文件,还可以执行其他语言编译后的字节码文件,是一个跨语言平台

2.JVM的组成部分

  1. 类加载器(ClassLoader)
  2. 运行时数据区(Runtime Data Area)
  3. 本地方法库(Execution Engine)
  4. 执行引擎(Native Interface)

程序在执行过程中需要把java文件转换为字节码文件,然后通过类加载器将文件存储在内存中的运行时数据区,而字节码文件是JVM的一套指令集规范,并不能直接交给底层系统去执行,因此需要特定命令的解析器执行引擎,将字节码编译为底层系统指令载交给cpu去执行,而这个过程中需要调用本地方法接口去实现整个程序的功能.

二.JVM类加载

1.类加载概述

类加载子系统负责从文件系统或网络中加载字节码文件,它只负责加载字节码文件,至于可不可以运行,则有执行引擎决定

2.类加载过程

2.1加载

使用流将硬盘上的字节码文件加载到内存中的运行时数据区的方法区,并生成对象的class对象

2.2链接

链接又分为三个步骤:

-验证:验证字节码格式是否正确,对字节码描述的信息进行语义分析,以保证其描述的信息符合java的语言规范

-准备:为类中的静态属性进行赋值(赋的值为0,在初始化阶段在进行赋值)

    static int a=123;   准备阶段a的值为0,在初始化阶段才赋值为123

-解析:将字节码中的逻辑引用替换为直接引用

逻辑引用:字节码中的逻辑符号

符号引用:内存地址

2.3初始化

为类的静态变量进行正确的赋值

类什么时候会初始化?

类只要被用到了都会被加载

1.new对象

2.加载子类时

3.反射机制

4.运行类中的main方法

5.使用了类的静态成员(类.静态变量  类.静态方法)

类什么时候不会被加载?

1.只访问了类的静态常量

2.创建的数组对象,只是作为类型存在

3.类加载器的分类

jvm角度来说,应该被分为俩类:

1.引导类加载器,使用 C/C++语言实现,嵌套在 JVM 内部.它用来加载 java 核心类库.

2.其他所有类加载器,这些类加载器全部由java语言实现,独立存在于jvm外部,并且全部继承自抽象类 java.lang.ClassLoader

站在java程序员的角度应该被分为三类:

1.引导类加载器

2.扩展类加载器,从 java.ext.dirs 系统属性所指定的目录中加载类库,或从 JDK 系统安装目录jre/lib/ext 子目录(扩展目录)下加载类库

3.应用程序类加载器,加载我们自己定义的类,用于加载用户类路径(classpath)上所有的类

4.双亲委派机制

java虚拟机对class文件采用的是按需加载的方式,也就是需要用到类时才把他的class文件加载到内存中生成class对象,在加载某个类的字节码文件时,jvm采用了双亲委派机制,即把请求交给父类处理,是一种任务委派机制.

工作原理:

如果一个类加载器收到了类加载请求,这个类加载器并不会自己先加载,而是将请求委托给父类的加载器去执行,如果父类加载器还存在父类,则继续向上委托,一次递归,直至得到顶层的启动类加载器,如果父类的加载器可以完成加载任务就成功返回,然后无法完成,子类才会自己尝试加载,如果均加载失败,就会抛出 ClassNotFoundException 异常

优点:安全,可以避免自己写的类替换java的核心类

如何打破双亲委派机制?

可以自定义类加载器

在 ClassLoader 类中涉及类加载的方法有两个,loadClass(String name), findClass(String name),这两个方法并没有被 final 修饰,也就表示其他子类可以重写.

三.运行时数据区

1.运行时数据区组成概述

2.程序计数器

用来记录下一条指令的地址,也就是即将要执行的指令,由执行引擎执行

特点:

它是一块很小的内存区域,也是运行速度最快的存储区域

在JVM规范中,每个线程都有一个计数器,是线程私有的,他的生命周期与线程一致
会记录当前线程正在执行的java程序的JVM指令地址
是唯一一个JVM规范中没有规定任何OutOfMemoryError情况的区域

3.虚拟机栈

Java 虚拟机栈(Java Virtual Machine Stack),早期也叫 Java 栈.每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个栈帧,对应着一次方法的调用.Java 虚拟机栈是线程私有的.主管 Java 程序的运行,它保存方法的局部变量(8种基本数据类型,对象的引用地址),部分结果,并参与方法的调用和返回.
栈的特点:
栈是一种快速有效的分配存储方式,访问速度仅次于程序计数器.
JVM 直接对 java 栈的操作只有两个:调用方法 入栈 .执行结束后 出栈 .
对于栈来说不存在垃圾回收问题
栈中会出现异常,当 线程请求的栈深度大于虚拟机所允许的深度时, 会出现StackOverflowError.
栈帧的内部结构:
局部变量表:局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。
操作数栈: 是用来对表达式求值,程序中的所有计算过程都是在借助于操作数栈来完成的。
方法返回地址:当一个方法执行完毕之后,要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址.

4.堆

《Java 虚拟机规范》中对 Java 堆的描述是:所有的对象实例都应当在运行时分配在堆上.
堆也是 Java 内存管理的核心区域.是 JVM 管理的最大一块内存空间.
堆内存的大小是可以调节. 例如: -Xms:10m(堆起始大小) -Xmx:30m(堆最大内存大小)
所有的线程共享 Java 堆
堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除.
堆是 GC(Garbage Collection,垃圾收集器)执行垃圾回收的重点区域.

4.1堆内存的划分

在JDK1.8被分为新生代老年代,新生代又被分为伊甸园区幸存者区

为什么分区(分代)?

根据对象的存活概率进行分区,将存活时间长的放到老年代,减少扫描垃圾的时间和GC频率,针对分类进行不同的垃圾回收算法,对算法扬长避短。

对象创建内存分配过程

将刚创建的新对象放到伊甸园区,当垃圾回收时将幸存下来的对象放到幸存者0区,再次进行垃圾回收时,将幸存者0区和伊甸园区的对象放到幸存者1中,每次保证有一个幸存者区是空闲的.当一个对象经历15次垃圾回收(被回收对象默认次数是15,可以通过-XX:MaxTenuringThreshold=<N>设置次数)时依然存活,会被放入老年区,或者如果一个对象比较的,也可以直接存放到老年区中.在老年代,相对悠闲,当老年代内存不足时,触发 GC,进行老年代的内存清理. 若老年代执行了 GC 之后发现依然无法进行对象存储,会对整堆进行 GC, 之后依然无法进行对象存储, 就会产生 OOM 异常. Java.lang.OutOfMemoryError:Java heap space

为什么是15次?

在对象头中,它由4位数据去对GC年龄进行记录保存,最大为1111,即15

5.方法区

一个被线程共享的区域,主要存储加载的类字节码、class/method/field 等元数据、static final 常量、static 变量、即时编译器编译后的代码等数据。在物理上与堆是属于同一个空间,但在逻辑上对其进行区分,被称为元空间

方法区在 JVM 启动时被创建,并且它的实际的物理内存空间中和 Java 堆区一样都可以是不连续的.
方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展.
方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出, 虚拟机同样会抛出内存溢出的错误
关闭 JVM 就会释放这个区域的内存

6.本地方法栈

Java 虚拟机栈管理 java 方法的调用,而本地方法栈用于管理本地方法的调用.
本地方法栈也是线程私有的.
允许被实现成固定或者是可动态扩展的内存大小.内存溢出方面也是相同的. 如果线程请求分配的栈容量超过本地方法栈允许的最大容量抛出StackOverflowError.
本地方法是用 C 语言写的.
它的具体做法是在 Native Method Stack 中登记 native 方法,在 Execution Engine 执行时加载本地方法库.

四.本地方法接口

1.什么是本地方法?

简单来说,被native修饰的方法就是本地方法,该类方法底层不是由java语言编写,例如c

2.为什么使用本地方法?

与java环境外交互,与硬件设备交互,java属于应用程序语言,没有与硬件设备直接交互的权限

五.执行引擎

将字节码解释/编译为对应平台上的本地机器指令

什么是解释器和编译器?

解释器: 当 Java 虚拟机启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行。
JIT(Just In Time Compiler)编译器: 就是虚拟机将源代码一次性直接编译成和本地机器平台相关的机器语言,但并不是马上执行。
为什么这样设计?

解释执行虽然效率低,但是在程序开始执行后可以立即投入使用,编译执行虽然将一些热点代码编译后缓存起来,执行效率高,但是需要花费一定时间,所以就采用开始时使用解释器执行,等编译器编译完成后就采用编译执行

六.垃圾回收机制

1.垃圾回收概述

1.1什么是垃圾?

垃圾是指没有被任何引用指向的对象,这个对象就是需要被回收的垃圾.

如果垃圾长时间不回收,这些垃圾对象会一直占用内存空间,导致空间无法被其他对象所使用,直到应用程序关闭,甚至导致内存溢出.

1.2垃圾回收概述

早期的 C/C++时代,垃圾回收基本上是手工进行的,开发人员可以使用 new 关键字进行内存申请,并使用 delete 关键字进行内存释放。这种方式可以灵活控制内存释放的时间,但是会给开发人员带来频繁申请和释放内存的管理负担。倘若有一处内存区间由于程序员编码的问题忘记被回收,那么 就会产生内存泄漏,垃圾对象永远无法被清除,随着系统运行时间的不断增长,垃圾对象所耗内存可能持续上升,直到出现内存溢出并造成应用程序崩溃。

现在,除了 Java 以外,C#、Python、Ruby 等语言都使用了自动垃圾回收的思想,也是未来发展趋势,可以说这种自动化的内存分配和来及回收方式已经成为了现代开发语言必备的标准。
垃圾收集器可以对年轻代,也可以对老年代,方法区的回收,其中,Java 堆是垃圾收集器的工作重点
从次数上讲:
频繁收集 Young 区
较少收集 Old 区
基本不收集元空间(方法区)

2.垃圾回收的相关算法

2.1垃圾回收标记阶段算法
标记阶段的目的: 主要是为了判断对象是否是垃圾对象
2.1.1引用计数算法
引用计数算法(Reference Counting)比较简单,对每个对象保存一个整型的引用计数器属性。用于记录对象被引用的情况。
工作原理:对于一个对象 A,只要有任何一个引用指向了对象 A,则对象 A 的引用计数器 就加 1;当引用失效时,引用计数器就减 1。只要对象 A 的引用计数器的值为 0,即表示对象 A 不可能再被使用,可进行回收
优点: 实现简单,垃圾对象便于辨识;判定效率高,回收没有延迟性。
缺点:
1.它需要单独的字段存储计数器,这样的做法 增加了存储空间的开销
2.无法解决循环引用问题
多个对象之间相互引用,计数器不为0,但是此时这几个对象,与外界已经没有联系了,使用不到了,他们相互又有引用,垃圾收集器不能回收他们,造成内存泄漏
2.1.2可达性分析算法
可达性分析算法:也可以称为根搜索算法、追踪性垃圾收集,这里的可达性分析就是 Java、C#选择的
相对于引用计数算法而言,可达性分析算法不仅同样具备实现简单和执行高效等特点,更重要的是该算法可以有效地解决在引用计数算法中循环引用的问题 ,防止内存泄漏的发生。
工作原理:
可达性分析算法是以根(GCRoots)为起始点,按照从上至下的方式搜索被根对象所连接的目标对象是否可达。使用可达性分析算法后,内存中的存活对象都会被根直接或间接连接着,搜索所走过的路径称为引用链(Reference Chain)如果目标对象没有任何引用链相连,则是不可达的,就意味着该对象己经死亡,可以标记为垃圾对象。

哪些对象可以称为活跃对象(GCroots)?
1.虚拟机栈中引用的对象
2.方法区中类静态属性引用的对象
3.所有同步锁synchronized持有的对象
4.java虚拟机内部的引用
基本数据类型对应的class对象,一些常驻的异常对象(nullpointerexception,outofmemoryerror),系统类加载器

2.2垃圾回收阶段算法
当成功区分出内存中存活对象和死亡对象后,GC 接下来的任务就是执行垃
圾回收,释放掉无用对象所占用的内存空间,以便有足够的可用内存空间为新对
象分配内存。目前在 JVM 中比较常见的三种垃圾收集算法是:
标记-复制算法(Copying)
标记-清除算法(Mark-Sweep)
标记-压缩算法(Mark-Compact)
2.2.1  标记-复制算法(Copying)
将可用内存空间分为两块,使用是只使用一块,在垃圾回收时,会将正在使用的内存空间中的存活对象复制到未使用的内存空间中,然后将正在使用的内存空间的所有对象进行回收,交换两个空间的角色,完成垃圾回收
复制算法适合存活对象少,垃圾对象多,特别适合收新生代。
2.2.2  标记-清除算法(Mark-Sweep)
清除: 这里所谓的清除并不是真的置空,而是把需要清除的对象地址保存在空闲的地址列表里。下次有新对象需要加载时,判断垃圾的位置空间是否够,如果够,就存放(也就是覆盖原有的地址)。
2.2.3  标记-压缩算法(Mark-Compact)
将所有的存活对象压缩到内存的一端,按顺序排放。之后,清理边界外所有的空间。
复制算法的高效性是建立在存活对象少、垃圾对象多的前提下的。这种情况在新生代经常发生,但是在老年代,更常见的情况是大部分对象都是存活对象。
如果依然使用复制算法,由于存活对象较多,复制的成本也将很高。因此,基于老年代垃圾回收的特性,需要使用其他的算法。
标记-清除算法的确可以应用在老年代中,但是在执行完内存回收后还会产生内存碎片,所以 JVM 的设计者需要在此基础之上进行改进。
标记-压缩算法的最终效果等同于标记-清除算法执行完成后,再进行一次内存碎片整理,因此,也可以把它称为标记-清除-压缩(Mark-Sweep-Compact)算法。
二者的本质差异在于标记-清除算法是一种非移动式的回收算法(空闲列表记录位置),标记-压缩是移动式的。

3.垃圾回收器

如果说垃圾收集算法是内存回收的方法论,那么收集器就是内存回收的实践者.
垃圾收集器没有在 java 虚拟机规范中进行过多的规定,可以由不同的厂商、不同版本的 JVM 来实现。
由于 JDK 的版本处于高速迭代过程中,因此 Java 发展至今已经衍生了众多的垃圾回收器。从不同角度分析垃圾收集器,可以将 GC 分为不同的类型。
3.1垃圾回收器分类
按线程数可以分为 单线程(串行) 垃圾回收器和 多线程(并行) 垃圾回收器
按照工作模式分,可以分为 独占式 并发式 垃圾回收器。
按工作的内存区间分,又可分为 年轻代垃圾回收器 老年代垃圾回收器。
3.2垃圾回收器的性能指标
吞吐量:运行用户代码的时间占总运行时间的比例 (总运行时间:程序的运行时间+ 内存回收的时间)
垃圾收集开销:垃圾收集所用时间与总运行时间的比例。
暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间。
内存占用: Java 堆区所占的内存大小。
3.3CMS回收器
CMS(Concurrent Mark Sweep,并发标记清除)收集器是以获取最短回收停顿时间为目标的收集器( 追求低停顿 ),它在垃圾收集时使得用户线程和 GC 线程并发执行,因此在垃圾收集过程中用户也不会感到明显的卡顿。
垃圾回收过程
初始标记:Stop The World,仅使用一条初始标记线程对所有与 GC Roots 直接关联的对象进行标记。
并发标记:垃圾回收线程,与用户线程并发执行。此过程进行可达性分析,标记出所有废弃对象。
重新标记:Stop The World,使用多条标记线程并发执行,将刚才并发标记过程中新出现的废弃对象标记出来。
并发清除:只使用一条 GC 线程,与用户线程并发执行,清除刚才标记的对象。这个过程非常耗时。
并发标记与并发清除过程耗时最长,且可以与用户线程一起工作,因此,总体上说,CMS 收集器的内存回收过程是与用户线程一起并发执行的。
3.4G1回收器
G1(Garbage-First)垃圾回收器是在 Java7 update 4 之后引入的一个新的垃圾回收器,是当今收集器技术发展的最前沿成果之一.是一款面向服务端应用的垃圾收集器。
G1 是一个并行回收器,它把堆内存分割为很多不相关的区域(Region)(物理上不连续的逻辑上连续的)。使用不同的 Region 来表示 Eden、幸存者0 区,幸存者 1 区,老年代等。
G1 GC 有计划地避免在整个 Java 堆中进行全区域的垃圾收集。G1 跟踪各个 Region 里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的 Region.
由于这种方式的侧重点在于回收垃圾最大量的区间(Region),所以我们给 G1 一个名字:垃圾优先(Garbage First)。
① 初始标记:标记出 GC Roots 直接关联的对象,这个阶段速度较快,需要停止用户线程,单线程执行。
② 并发标记:从 GC Root 开始对堆中的对象进行可达新分析,找出存活对象,这个阶段耗时较长,但可以和用户线程并发执行。
③ 最终标记:修正在并发标记阶段引用户程序执行而产生变动的标记记录。

④ 筛选回收:筛选回收阶段会对各个 Region 的回收价值和成本进行排序,根据用户所期望的 GC 停顿时间来指定回收计划(用最少的时间来回收包含垃圾最多的区域.这就是 Garbage First 的由来——第一时间清理垃圾最多的区块),这里为了提高回收效率,并没有采用和用户线程并发执行的方式,而是停顿用户线程。
适用场景:要求尽可能可控 GC 停顿时间;内存占用较大的应用。

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com