b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

Java内存泄漏是每个Java程序员都会遇到的的问题

电脑杂谈  发布时间:2021-02-22 10:05:27  来源:网络整理

Java内存泄漏是每个Java程序员都会遇到的问题。该程序通常在本地运行,但是当部署到远程端时,内存将无限增长,最后系统瘫痪了,那么最快最好的测试程序的稳定性如何才能防止系统崩溃,作者运用自己的个人经验与您分享这些问题的解决方案。

作为Internet上最流行的编程语言之一,Java现在非常流行。我们的Web应用程序主要是用Java语言开发的,大致分为三个级别:客户端,服务器和。在进行测试的过程中,我们发现程序模块系统的内存和CPU资源消耗迅速增加,并且一直持续增长,直到发生java.lang.OutOfMemoryError为止。经过分析,Java内存泄漏是破坏系统的主要因素。在这里与您分享我们在开发过程中遇到的Java内存泄漏检测和解决过程。

一. Java如何管理内存

为了判断Java中是否存在内存泄漏,我们必须首先了解Java如何管理内存。 Java内存管理是对象的分配和释放。在Java中,内存分配是由程序完成的,而内存的释放是由垃圾回收器(Garbage Collection,GC)完成的。程序员无需调用函数来释放内存,而只能回收由内存占用的空间。那些无用且不再被其他对象引用的对象。

Java的内存垃圾回收机制是从程序的主要运行对象检查引用链。在遍历它之后,发现未引用的隔离对象被视为垃圾回收。为了正确释放对象,GC必须监视每个对象的状态。 GC需监视对象的运行状态,包括对象的应用程序,引用,引用,分配等。监视对象的状态是为了更准确,及时地释放对象,释放对象的基本原理是不再引用对象。

在Java中,这些无用的对象由GC收集,因此程序员不需要考虑这部分内存泄漏。虽然,我们有几个可以访问GC的函数,例如运行GC的System.gc()函数,但是根据Java语言规范的定义,此函数不能保证JVM的垃圾收集器将被执行。因为不同的JVM实现者可能使用不同的算法来管理GC。通常,GC线程的优先级较低。 JVM调用GC策略的方法也很多。有些是当内存使用量达到一定水平时GC开始工作,有些会定期执行,有些会顺利执行,有些会中断。但总的来说,我们不需要关心这些。

二.什么是Java中的内存泄漏

内存泄漏的主要原因是您之前申请了内存空间,却忘记释放它。如果程序中有对无用对象的引用,则这些对象将驻留在内存中并消耗内存,因为垃圾回收器无法通过GC验证是否不再需要这些对象。如果存在对该对象的引用,则该对象被定义为“有效活动”,并且不会被释放。为了确定该对象占用的内存将被回收,我们必须确认该对象不会被再次使用。典型的方法是将对象数据成员设置为null或从集合中删除对象。但是,当不需要局部变量时,不必将其显式设置为null,因为在执行方法时,这些引用将被自动清除。

在Java中,内存泄漏是某些分配对象的存在。这些对象具有以下两个特征。首先,引用这些对象,即在有向树图中,存在可以连接到它们的分支。 其次,这些对象是无用的,也就是说,程序将来将不再使用这些对象。如果对象满足这两个条件,则可以将这些对象判断为Java中的内存泄漏,并且GC将不会回收这些对象,但是它将占用内存。

这是一个常见的示例。在下面的代码中,循环申请Object对象,然后将应用的对象放入Vector。如果仅释放对象本身,但由于Vector仍引用该对象,则该对象不可回收用于GC。因此,如果将对象添加到Vector,则必须将其从Vector中删除。最简单的方法是将Vector对象设置为null。

实际上,这些对象已经无用,但仍被引用,并且GC无法执行任何操作(实际上,GC认为它仍然有用)。这是内存泄漏的最重要原因。让我引用另一个示例来说明Java内存泄漏。假设有一个日志类Logger提供了一个静态日志(字符串msg),则其他任何类都可以调用Logger.Log(消息)以将消息的内容记录到系统日志文件中。

Logger类具有HashMap类型的静态变量temp。每次执行日志(消息)时,先将message的值写入temp(使用当前线程+当前时间作为键),然后再退出,然后从temp中删除当前线程和当前时间作为键的条目。请注意,此处的当前时间是不断变化的,因此在日志退出之前删除条目的操作不会删除在执行开始时写入的条目。这样,Logger的静态变量temp最终会引用任何作为参数传递给log的字符串,并且无法回收。这种对象保留就是我们所说的Java内存泄漏。通常,内存管理中发生内存泄漏的主要原因是:保留了对象引用,但再也没有使用过。

三.几种典型的内存泄漏

我们知道Java中存在内存泄漏,因此让我们看一下几种典型的泄漏,并找出造成这些泄漏的原因和解决方案。

3. 1个全球收藏

在大型应用程序中拥有各种全局数据仓库(例如JNDI树或会话表)是很常见的。在这些情况下,必须注意管理存储库的大小。必须有某种机制从存储库中删除不再需要的数据。

通常有许多不同的解决方案,其中最常见的是定期运行的清理作业。该作业将验证仓库中的数据,然后清除所有不必要的数据。管理存储库的另一种方法是使用引荐来源网址计数。然后,该集合负责计算集合中每个条目的反向链接数。这需要反向链接告诉集合何时退出条目。当反向链接数为零时,可以将元素从集合中移除。

3. 2缓存

缓存用于快速查找已执行操作结果的数据结构。因此,如果一个操作需要更多的资源来执行并且将被多次使用,则通常的做法是执行常用输入数据缓存的操作结果,以便在下次调用该操作时使用缓存的数据。缓存通常以动态方式实现。如果缓存设置不正确,并且使用了大量缓存,则会发生内存溢出的后果,因此需要更改使用的内存容量。与数据检索的速度保持平衡。

常见的解决方案是使用java.lang.ref.SoftReference类坚持将对象放入高速缓存中。此方法可以确保当虚拟机内存不足或需要更多堆时,可以释放对这些对象的引用。

java内存泄漏检测工具_linux 内存泄漏检测_java内存泄漏怎么解决

3. 3类加载器*****

Java类加载器的使用为内存泄漏提供了许多机会。通常,类加载器具有复杂的结构,因为类加载器不仅与“常规”对象引用相关,而且与对象的内部引用也相关。例如数据变量,方法和各种类。这意味着只要存在用于数据变量,方法,各种类和对象的类加载器,该类加载器将驻留在JVM中。由于类加载器可以与许多类以及静态数据变量关联,因此可能会泄漏大量内存。

四.如何检测和处理内存泄漏

如何查找内存泄漏的原因通常有两个步骤:首先是安排有经验的程序员逐步分析代码,以找出内存泄漏发生的位置。第二种是使用专用的内存泄漏测试工具进行测试。

第一步:在代码演练中,可以安排熟悉系统业务和开发语言工具的开发人员对应用程序代码进行交叉检查,并尝试在代码中查找连接语句。并且结果集没有关闭,代码冗余等故障代码。

第二步:检测Java内存泄漏。在这里,我们通常使用一些工具来检查Java程序的内存泄漏。市场上有几种检查Java内存泄漏的工具,它们的基本工作原理类似和微小的不同都是通过在Java程序运行时监视应用程序和所有对象的释放来实现的,所有内存管理信息都是计数,分析和可视化。开发人员将根据此信息确定程序是否存在内存泄漏。这些工具包括Optimizeit Profiler,JProbe Profiler,JinSight,Rational Purify等。

4. 1检测到内存泄漏

在这里,我们将简要介绍我们使用Optimizeit进行检查的过程。通常,在知道发生了内存泄漏之后,第一步就是找出哪些数据已泄漏以及哪种类型的对象导致了泄漏。

通常来说,正常系统的内存使用情况在稳定运行之后基本稳定,因此不应无限制地增加。同样,有一个相对的。稳定的上限不应继续增长。根据此基本假设,我们继续观察系统使用的内存大小以及系统运行时的实例数。如果内存大小继续增长,则意味着系统存在内存泄漏。 ,如果特定类的实例对象的数量随时间增长(所谓的“增长率”),则意味着该类的实例可能会泄漏。

另一方面,通常会出现内存泄漏的第一个迹象是:OutOfMemoryError出现在应用程序中。在这种情况下,您需要使用一些开销较小的工具来监视和查找内存泄漏。尽管也可能发生OutOfMemoryError,但应用程序确实使用了太多内存。在这种情况下,您可以增加JVM可用的堆数量,或对应用程序进行一些更改以使其使用更少的内存。

但是,在许多情况下,OutOfMemoryError是内存泄漏的信号。一种发现的方法是连续监视GC的活动,以确定内存使用量是否随时间增加。如果这样做,可能会发生内存泄漏。

4. 2处理内存泄漏的方法

一旦您知道确实发生了内存泄漏,就需要更的工具来找出发生泄漏的原因。 JVM本身不会告诉您。这些工具从JVM获得内存系统信息的方法基本上有两种:JVMTI和字节码检测。 Java虚拟机工具接口(JVMTI)及其前身Java虚拟机概要分析接口(JVMPI)是外部工具和JVM。JVM是用于从JVM通信和收集信息的标准化接口。字节码技术是指使用探针处理字节码以获得工具所需信息的技术。

Optimizeit是Borland的产品,主要用于辅助代码优化和软件系统的故障诊断。 Optimizeit Profiler主要用于分析内存泄漏。 Profiler的堆视图用于观察系统使用的内存量。以及为每个类分配的实例数。

首先,Profiler将执行趋势分析以找出泄漏的对象类型。系统长时间运行后,可以获得四个内存快照。如果每个快照的内存使用量都比上次增加,则对这四个内存快照进行全面分析。可以确定系统内存泄漏。找出四个快照中实例数量增加的类。这些类最初可以标识为泄漏。通过数据收集和初步分析,可以得出初步结论:系统中是否存在内存泄漏以及哪些对象被泄漏(泄漏)。

接下来,让我们看一下其他哪些类与泄漏的类的对象相关联。如前所述,Java中的内存泄漏是无用的对象保留。简而言之,是由于编码错误导致应该存在的引用链的存在(因此导致无法释放被引用的对象),因此内存泄漏分析的任务是找出此冗余引用链并找出其形成的原因。查看对象的分配位置很有用。同时,还不足以知道它们与其他对象的关系(即哪些对象引用了它们),有关它们在何处创建的信息也很有用。

最后,进一步研究单个对象,并查看它们之间的关系。借助Profiler工具,可以在分配过程中动态添加应用程序中的代码以创建堆栈跟踪。也可以在系统中分配所有对象。执行动态堆栈跟踪。这些堆栈跟踪可以在工具中累积和分析。对于每个泄漏的实例对象,必须存在从拉取对象到对象的引用链。堆栈空间中的拉动对象从堆栈中弹出后,便失去了拉动的能力,并成为非拉动对象。因此,经过长时间的操作,泄漏的对象基本上由拉对象作为类的静态变量来拉。

简而言之,尽管Java具有自动回收和管理内存的功能,但不能忽略内存泄漏。这通常是破坏系统稳定性的重要因素。

Windows随附的Java内存视图命令

java内存泄漏怎么解决_linux 内存泄漏检测_java内存泄漏检测工具

jinfo:可以在运行时输出和修改java进程的选择。

jps:类似于UNIX上的ps,它用于显示本地Java进程,您可以查看在本地运行的多个Java程序,并显示其进程号。

jstat:一个非常强大的工具,用于监视VM内存。它可用于监视VM内存中各种堆和非堆的大小及其内存使用情况。

jmap:打印出Java进程内存中的所有“对象”(使用pid)(例如那些对象及其编号)。

jconsole:一个Java GUI监视工具,可以图形形式显示各种数据。并可以通过远程连接监视远程服务器VM。

详细信息:在使用这些工具之前,请使用JPS命令获取每个JVM的当前进程号,然后选择要查看的JVM。

jstat工具非常强大,具有许多选项,堆的每个部分的用法的详细视图以及已加载类的数量。使用时,需要添加查看过程的过程ID和所选参数。下面详细介绍每个参数的含义。

jstat -class pid:显示诸如已加载类的数量和所占用的空间之类的信息。

jstat -compiler pid:显示诸如VM的实时编译数量之类的信息。

jstat -gc pid:可以显示gc信息,检查gc的数量和时间。最后五个项目是年轻gc的数量,年轻gc的时间,完整gc的数量,完整gc的时间以及gc的总时间。

jstat -gccapacity:可以显示VM内存中三代(年轻,旧,烫发)对象的使用情况和占用率,例如:PGCMN显示最小烫发的内存使用情况,PGCMX显示最大的内存使用情况烫发的百分比PGC是新生成的烫发的内存占用,而PC是先前烫发的内存占用。可以用这个比喻来推论其他人,OC是古老的纯粹居住。

jstat -gcnew pid:新的对象信息。

jstat -gcnewcapacity pid:有关新对象及其占用率的信息。

jstat -gcold pid:旧对象信息。

jstat -gcoldcapacity pid:旧对象信息及其占用情况。

jstat -gcpermcapacity pid:烫发对象信息及其占用。

jstat -util pid:统计gc信息统计。

jstat -printcompilation pid:当前VM执行信息。

除了以上参数外,还可以同时添加两个数字,例如:jstat -printcompilation 3024 250每250毫秒打印6次,共6次打印,还可以添加-h3来显示每三行显示一次标题。

java内存泄漏检测工具_java内存泄漏怎么解决_linux 内存泄漏检测

jmap是一个工具,可以输出内存中的所有对象,甚至可以将VM中的堆输出为二进制文本。

命令:jmap -dump:format = b,file = heap.bin

文件:保存路径和文件名

pid:进程号

•jmap -histo:live pid |更少:堆中的活动对象及其大小

•jmap -heap pid:查看堆使用情况信息

jinfo:用法相对简单,即可以在运行时输出和修改java进程的运行参数。用法是jinfo -opt pid。例如,您可以使用jinfo -flag MaxPermSize 2788查看MaxPerm大小2788。

jconsole是用Java编写的GUI程序。它用于监视VM,并且可以监视远程VM。它非常易于使用且功能强大。用法:在命令行中点击jconsole并选择进程。

java内存泄漏检测工具

有关JConsole中内存分区的说明。

Eden空间(堆):最初,该线程池中的内存分配给了大多数对象。

幸存者空间(堆):用于将垃圾回收后尚未回收的对象存储在伊甸空间内存池中。

持久生成(堆):用于将幸存者空间内存池中的对象保留一段时间。

永久生成(非堆):保存虚拟机自身的静态(恢复性)数据,例如类和方法对象。 Java虚拟机共享这些类型的数据。该区域分为只读和只写

代码缓存(非堆):HotSpot Java虚拟机包括一个用于编译和保存本机代码的内存,称为“代码缓存”

•jstack(检查jvm线程的运行状态,是否存在死锁现象等):jstack pid:线程转储

•jstat -gcutil pid 1000 100:在1000毫秒内计算100次GC状态; <​​/ p>

还建议使用内存对象工具MemoryAnalyzer来查看jmap转储

URL:您可以在转储期间查看对象数,内存使用情况,线程状态等。

并使用内存分析器工具分析内存泄漏


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-359711-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...