草庐IT

内存溢出、内存泄露的概述及常见情形

墨鸦_Cormorant 2023-04-19 原文

内存溢出(OutofMemoryError)

简述

java doc 中对 Out Of Memory Error 的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存。

JVM 提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,由于 GC(垃圾回收)一直在发展,所有一般情况下,除非应用程序占用的内存增长速度非常快,造成垃圾回收已经跟不上内存消耗的速度,否则不太容易出现内存泄漏和内存溢出问题。但是基本不会出现并不等于不会出现,所以掌握 Java 内存模型原理和学会分析出现的内存溢出或内存泄漏仍然十分重要。

大多数情况下,GC 会进行各种年龄段的垃圾回收,实在不行了就放大招,来一次独占式的 Full GC 操作,这时候会回收大量的内存,供应用程序继续使用。

在抛出 OutofMemoryError 之前,通常垃圾收集器会被触发,尽其所能去清理出空间。例如:在引用机制分析中,涉及到 JVM 会去尝试回收软引用指向的对象等。在 java.nio.BIts.reserveMemory() 方法中,System.gc() 会被调用,以清理空间。

当然,也不是在任何情况下垃圾收集器都会被触发的。比如,分配了一个超大对象,类似一个超大数组超过堆的最大值,JVM 可以判断出垃圾收集并不能解决这个问题,所以直接抛出 OutofMemoryError。


内存溢出的常见情形

不同的内存溢出错误可能会发生在内存模型的不同区域,因此,需要根据出现错误的代码具体分析来找出可能导致错误发生的地方,并想办法进行解决。

  • 栈内存溢出(StackOverflowError)

    栈内存可以分为虚拟机栈(VM Stack)和本地方法栈(Native Method Stack),除了它们分别用于执行 Java 方法(字节码)和本地方法,其余部分原理是类似的。

    以虚拟机栈为例说明,Java 虚拟机栈是线程私有的,当线程中方法被调度时,虚拟机会创建用于保存局部变量表、操作数栈、动态连接和方法出口等信息的栈帧(Stack Frame)。

    具体来说,当线程执行某个方法时,JVM 会创建栈帧并压栈,此时刚压栈的栈帧就成为了当前栈帧。如果该方法进行递归调用时,JVM 每次都会将保存了当前方法数据的栈帧压栈,每次栈帧中的数据都是对当前方法数据的一份拷贝。如果递归的次数足够多,多到栈中栈帧所使用的内存超出了栈内存的最大容量,此时 JVM 就会抛出 StackOverflowError。

    总之,不论是因为栈帧太大还是栈内存太小,当新的栈帧内存无法被分配时,JVM 就会抛出 StackOverFlowError。

    优化方案:

    • 可以通过设置 JVM 启动参数 -Xss 参数来改变栈内存大小。

      注:分配给栈的内存并不是越大越好,因为栈内存越大,线程多,留给堆的空间就不多了,容易抛出OOM。JVM的默认参数一般情况没有问题(包括递归)。

    • 递归调用要控制好递归的层级,不要太高,超过栈的深度。

    • 递归调用要防止形成死循环,否则就会出现栈内存溢出。

  • 堆内存溢出(OutOfMemoryError:java heap space)

    堆内存的唯一作用就是存放数组和对象实例,即通过 new 指令创建的对象,包括数组和引用类型。

    堆内存溢出又分为两种情况:

    • Java 虚拟机的堆内存设置不够

      如果堆的大小不合理(没有显式指定 JVM 堆大小或者指定数值偏小),对象所需内存太大,创建对象时分配空间,JVM 就会抛出 OutOfMemoryError:java heap space 异常。

      优化方案:

      • 如果要处理比较可观的数据量,可以通过修改 JVM 启动参数 -Xms 、-Xmx 来调整。使用压力测试来调整这两个参数达到最优值。

      • 尽量避免大的对象的申请,例如文件上传,大批量从数据库中获取等。

        尽量分块或者分批处理,有助于系统的正常稳定的执行。

      • 尽量提高一次请求的执行速度,垃圾回收越早越好。

        否则,大量的并发来了的时候,再来新的请求就无法分配内存了,就容易造成系统的雪崩。

    • 堆内存泄露最终导致堆内存溢出

      当堆中一些对象不再被引用但垃圾回收器无法识别时,这些未使用的对象就会在堆内存空间中无限期存在,不断的堆积就会造成内存泄漏。不停的堆积最终会触发 java . lang.OutOfMemoryError。

      优化方案:如果发生了内存泄漏,则可以先找出导致泄漏发生的对象是如何被 GC ROOT 引用起来的,然后通过分析引用链找到发生泄漏的地方,进行代码优化。

  • 永久代溢出(OutOfMemoryError:PermGen sapce)

    对于老版本的 oracle JDK,因为永久代的大小是有限的,并且 JVM 对永久代垃圾回收(例如常量池回收、卸载不再需要的类型)非常不积极,所以当不断添加新类型的时候,永久代出现 OutOfMemoryError 也非常多见,尤其是在运行时存在大量动态类型生成的场合;类似 intern 字符串缓存占用太多空间,也会导致 OOM 问题,对应的异常信息,会标记出来和永久代相关:“java.lang.OutOfMemoryError:PermGen space"。

    随着元数据区的引入,方法区内存已经不再那么窘迫,所以相应的 OOM 有所改观,出现 OOM,异常信息则变成了:“java.lang.OutofMemoryError:Metaspace"。

  • 元空间内存溢出(OutOfMemoryError: Metaspace)

    元空间的溢出,系统会抛出 java.lang.OutOfMemoryError: Metaspace

    出现这个异常的问题的原因是系统的代码非常多或引用的第三方包非常多或者通过动态代码生成类加载等方法,导致元空间的内存占用很大。

    优化方案:

    • 默认情况下,元空间的大小仅受本地内存限制。

      但是为了整机的性能,尽量还是要对该项进行设置,优化参数配置,以免造成整机的服务停机。

    • 慎重引用第三方包

      对第三方包,一定要慎重选择,不需要的包就去掉。

      这样既有助于提高编译打包的速度,也有助于提高远程部署的速度。

    • 关注动态生成类的框架

      对于使用大量动态生成类的框架,要做好压力测试,验证动态生成的类是否超出内存的需求会抛出异常。

  • 直接内存溢出

    如果直接或间接(很多 java NIO,例如在 netty 的框架中被封装为其他的方法)使用了 ByteBuffer 中的 allocateDirect() 方法,而又不做 clear 的时候,就会抛出 java.lang.OutOfMemoryError: Direct buffer memory 异常。

    如果经常有类似的操作,可以考虑设置 JVM 参数:-XX:MaxDirectMemorySize,并及时 clear 内存。

  • 创建本地线程内存溢出

    除了堆以外的区域,无法为线程分配一块内存区域了(线程基本只占用堆以外的内存区域),要么是内存本身就不够,要么堆的空间设置得太大了,导致了剩余的内存已经不多了,而由于线程本身要占用内存,所以就不够用了。

    优化方案:

    • 首先检查操作系统是否有线程数的限制,如果使用 shell 也无法创建线程,就需要调整系统的最大可支持的文件数。
    • 日常开发中尽量保证线程最大数的可控制的,不要随意使用可以无限制增长的线程池。
  • 数组超限内存溢出

    JVM 在为数组分配内存之前,会执行特定平台的检查:分配的数据结构是否在此平台是可寻址的。

    一般来说 java 对应用程序所能分配数组最大大小是有限制的,只不过不同的平台限制有所不同,但通常在1到21亿个元素之间。当应用程序试图分配大于 Java 虚拟机可以支持的数组时会报 Requested array size exceeds VM limit 错误。

    不过这个错误一般少见的,主要是由于 Java 数组的索引是 int 类型。 Java 中的最大正整数为 2 ^ 31 - 1 = 2,147,483,647。 并且平台特定的限制可以非常接近这个数字,例如:Jdk1.8 可以初始化数组的长度高达 2,147,483,645(Integer.MAX_VALUE-2)。若是在将数组的长度再增加 1 达到 nteger.MAX_VALUE-1 ,就会出现 OutOfMemoryError 了。

    优化方案:数组长度要在平台允许的长度范围之内。

  • 超出交换区内存溢出

    在 Java 应用程序启动过程中,可以通过 -Xmx 和其他类似的启动参数限制指定的所需的内存。而当 JVM 所请求的总内存大于可用物理内存的情况下,操作系统开始将内容从内存转换为硬盘。

    当应用程序向 JVM native heap 请求分配内存失败并且 native heap 也即将耗尽时, JVM 会抛出Out of swap space 错误, 错误消息中包含分配失败的大小(以字节为单位)和请求失败的原因。

    优化方案:

    • 增加系统交换区的大小。

      但如果使用了交换区,性能会大大降低,不建议采用这种方式。

      生产环境尽量避免最大内存超过系统的物理内存。其次,去掉系统交换区,只使用系统的内存,保证应用的性能。

  • 系统杀死进程内存溢出

    操作系统是建立在进程的概念之上,这些进程在内核中作业,其中有一个非常特殊的进程,称为“内存杀手(Out of memory killer)”。当内核检测到系统内存不足时,OOM killer 被激活,检查当前谁占用内存最多然后将该进程杀掉。

    一般 Out of memory:Kill process or sacrifice child 报错会在当可用虚拟内存(包括交换空间)消耗到让整个操作系统面临风险内存不足时,会被触发。在这种情况下,OOM Killer 会选择“流氓进程”并杀死它。

    优化方案:

    • 增加交换空间的方式可以缓解 Java heap space 异常
    • 但还是建议最好的方案就是升级系统内存,让 java 应用有足够的内存可用,就不会出现这种问题。

内存泄漏(memory leak)

简述

  • 也称作“存储渗漏”。

  • 严格来说,只有对象不会再被程序用到了,但是 GC 又不能回收它们的情况,才叫内存泄漏。

    但实际情况很多时候一些不太好的实践(或疏忽)会导致对象的生命周期变得很长甚至导致 OOM,也可以叫做宽泛意义上的“内存泄漏”。

  • 尽管内存泄漏并不会立刻引起程序崩溃,但是一旦发生内存泄漏,程序中的可用内存就会被逐步蚕食,直至耗尽所有内存,最终出现 OutOfMemory 异常,导致程序崩溃。

    注意:这里的可用内存并不是指物理内存,而是指虚拟内存大小,这个虚拟内存大小取决于磁盘交换区设定的大小。

  • Java 使用可达性分析算法,最上面的数据不可达,就是需要被回收的。

    后期有一些对象不用了,按道理应该断开引用,但是存在一些链没有断开,从而导致没有办法被回收


可达性分析算法

可达性分析算法:判断对象是否是不再使用的对象,本质都是判断一个对象是否还被引用。那么对于这种情况下,由于代码的实现不同就会出现很多种内存泄漏问题(让 JVM 误以为此对象还在引用中,无法回收,造成内存泄漏)。

举例说明:

  • 对象 X 引用对象 Y,X 的生命周期比 Y 的生命周期长;
  • 那么当 Y 生命周期结束的时候,X 依然引用着 Y,这时候,垃圾回收期是不会回收对象 Y 的;
  • 如果对象 X 还引用着生命周期比较短的 A、B、C,对象 A 又引用着对象 a、b、c,这样就可能造成大量无用的对象不能被回收,进而占据了内存资源,造成内存泄漏,直到内存溢出。


Java 中内存泄漏的 8 种情况

  1. 静态集合类,如 HashMap、LinkedList 等等。

    如果这些容器为静态的,那么它们的生命周期与 JVM 程序一致,则容器中的对象在程序结束之前将不能被释放,从而造成内存泄漏。

    简而言之,长生命周期的对象持有短生命周期对象的引用,尽管短生命周期的对象不再使用,但是因为长生命周期对象持有它的引用而导致不能被回收。

  2. 单例模式

    单例模式,和静态集合导致内存泄露的原因类似,因为单例的静态特性,它的生命周期和 JVM 的生命周期一样长,所以如果单例对象如果持有外部对象的引用,那么这个外部对象也不会被回收,那么就会造成内存泄漏。

  3. 内部类持有外部类的引用

    在 Java 中内部类的定义与使用一般为成员内部类与匿名内部类,他们的对象都会隐式持有外部类对象的引用,影响外部类对象的回收。

    可以通过反编译可以来验证这个理论:

    • java 代码

      public class Outer {
          private String name;
          class Inner{
              private String test;
          }
      }
      
    • 反编译后的代码

      class Outer$Inner {
          private String test;
          final Outer this$0;
          Outer$Inner() {
              this.this$0 = Outer.this;
              super();
          }
      }
      

      可以清楚的发现,内部类的属性中有这个外部类,并且在内部类的构造函数中有这个外部类属性的初始化。

    如果一个外部类的实例对象的方法返回了一个内部类的实例对象,而这个内部类对象被长期引用了,那么即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象引用,这个外部类对象将不会被垃圾回收,这也会造成内存泄漏。

  4. 各种连接,如数据库连接、网络连接和 IO 连接等

    在对数据库进行操作的过程中,首先需要建立与数据库的连接,当不再使用时,需要调用 close 方法来释放与数据库的连接。只有连接被关闭后,垃圾回收器才会回收对应的对象。

    否则,如果在访问数据库的过程中,**对 Connection、Statement 或 ResultSet 不显性地关闭,将会造成大量的对象无法被回收,**从而引起内存泄漏。

  5. 变量不合理的作用域

    一般而言,一个变量的定义的作用范围大于其使用范围,很有可能会造成内存泄漏。另一方面,如果没有及时地把对象设置为 null,很有可能导致内存泄漏的发生。

    public class UsingRandom {
      private String msg;
      public void receiveMsg(){
         //private String msg;
         readFromNet(); // 从网络中接受数据保存到msg中
         saveDB(); // 把msg保存到数据库中
         //msg = null;
      }
    }
    

    如上面这个伪代码,通过 readFromNet 方法把接受的消息保存在变量 msg 中,然后调用 saveDB 方法把 msg 的内容保存到数据库中,此时 msg 已经就没用了,由于 msg 的生命周期与对象的生命周期相同,此时 msg 还不能回收,因此造成了内存泄漏。

    优化方案:

    • 方案1:这个 msg 变量可以放在方法内部,当方法使用完,那么 msg 的生命周期也就结束,就可以回收了。
    • 方案2:在使用完 msg 后,把 msg 设置为 null,这样垃圾回收器也会回收 msg 的内存空间。
  6. 改变哈希值

    当一个对象被存储进 HashSet 集合中以后,就不能修改这个对象中的那些参与计算哈希值的字段了。

    否则,对象修改后的哈希值与最初存储进 HashSet 集合中时的哈希值就不同了,在这种情况下,即使在 contains 方法使用该对象的当前引用作为的参数去 HashSet 集合中检索对象,也将返回找不到对象的结果,这也会导致无法从 HashSet 集合中单独删除当前对象,造成内存泄漏。

    这也是 String 为什么被设置成了不可变类型,可以放心地把 String 存入 HashSet,或者把 String 当做 HashMap 的 key 值;

    当想把自己定义的类保存到散列表的时候,需要保证对象的 hashCode 不可变。

    /**
     * 演示内存泄漏
     */
    public class ChangeHashCode1 {
        public static void main(String[] args) {
            HashSet hs = new HashSet();
            Point cc = new Point();
            cc.setX(10);//hashCode = 41
            hs.add(cc);
            cc.setX(20);//hashCode = 51
            System.out.println("hs.remove = " + hs.remove(cc));//false
            hs.add(cc);
            System.out.println("hs.size = " + hs.size());//size = 2
        }
    }
    
    class Point {
        int x;
    
        public int getX() return x;
        public void setX(int x) this.x = x;
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + x;
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null) return false;
            if (getClass() != obj.getClass()) return false;
            Point other = (Point) obj;
            if (x != other.x) return false;
            return true;
        }
    }
    
  7. 对象缓存泄漏

    一旦把对象引用放入到缓存中,就很容易遗忘。

    比如:代码中会加载一个表中的数据到缓存(内存)中,测试环境只有几百条数据,但是生产环境则可能会有几百万的数据。

    优化方案:可以使用 WeakHashMap 代表缓存,此种 Map 的特点是,当除了自身有对 key 的引用外,此 key 没有其他引用那么此 map 会自动丢弃此值。

    /**
     * 演示内存泄漏
     */
    public class MapTest {
        static Map wMap = new WeakHashMap();
        static Map map = new HashMap();
    
        public static void main(String[] args) {
            init();
            testWeakHashMap();
            testHashMap();
        }
    
        public static void init() {
            String ref1 = new String("obejct1");
            String ref2 = new String("obejct2");
            String ref3 = new String("obejct3");
            String ref4 = new String("obejct4");
            wMap.put(ref1, "cacheObject1");
            wMap.put(ref2, "cacheObject2");
            map.put(ref3, "cacheObject3");
            map.put(ref4, "cacheObject4");
            System.out.println("String引用ref1,ref2,ref3,ref4 消失");
    
        }
    
        public static void testWeakHashMap() {
    
            System.out.println("WeakHashMap GC之前");
            for (Object o : wMap.entrySet()) {
                System.out.println(o);
            }
            try {
                System.gc();
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("WeakHashMap GC之后");
            for (Object o : wMap.entrySet()) {
                System.out.println(o);
            }
        }
    
        public static void testHashMap() {
            System.out.println("HashMap GC之前");
            for (Object o : map.entrySet()) {
                System.out.println(o);
            }
            try {
                System.gc();
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("HashMap GC之后");
            for (Object o : map.entrySet()) {
                System.out.println(o);
            }
        }
    
    }
    /**
     * 结果
     * String引用ref1,ref2,ref3,ref4 消失
     * WeakHashMap GC之前
     * obejct2=cacheObject2
     * obejct1=cacheObject1
     * WeakHashMap GC之后
     * HashMap GC之前
     * obejct4=cacheObject4
     * obejct3=cacheObject3
     * Disconnected from the target VM, address: '127.0.0.1:51628', transport: 'socket'
     * HashMap GC之后
     * obejct4=cacheObject4
     * obejct3=cacheObject3
     **/
    

    上面代码演示 WeakHashMap 如何自动释放缓存对象:当 init 函数执行完成后,局部变量字符串引用 weakd1,weakd2,d1,d2 都会消失,此时只有静态 map 中保存中对字符串对象的引用,可以看到,调用 gc 之后,HashMap 的没有被回收,而 WeakHashMap 里面的缓存被回收了。

  8. 监听器和回调

    内存泄漏另一个常见来源是监听器和其他回调,如果客户端在实现的 API 中注册回调,却没有显式的取消,那么就会积聚。

    需要确保回调立即被当作垃圾回收的最佳方法是只保存它的弱引用,例如将它们保存成为 WeakHashMap 中的键。

有关内存溢出、内存泄露的概述及常见情形的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  3. git使用常见问题(提交代码,合并冲突) - 2

    文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g

  4. 阿里云RDS——产品系列概述 - 2

    基础版云数据库RDS的产品系列包括基础版、高可用版、集群版、三节点企业版,本文介绍基础版实例的相关信息。RDS基础版实例也称为单机版实例,只有单个数据库节点,计算与存储分离,性价比超高。说明RDS基础版实例只有一个数据库节点,没有备节点作为热备份,因此当该节点意外宕机或者执行重启实例、变更配置、版本升级等任务时,会出现较长时间的不可用。如果业务对数据库的可用性要求较高,不建议使用基础版实例,可选择其他系列(如高可用版),部分基础版实例也支持升级为高可用版。基础版与高可用版的对比拓扑图如下所示。优势 性能由于不提供备节点,主节点不会因为实时的数据库复制而产生额外的性能开销,因此基础版的性能相对于

  5. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  6. ruby - 将对象设置为 nil 是否很常见? - 2

    我正在构建一个应用程序,想知道是否将未使用的对象设置为nil是生产级编码中的常见做法。我知道这只是垃圾收集器的提示,并不总是处理对象。 最佳答案 根据这个thread如果您使用完一个成员对象,将其设置为nil将引发被引用对象被垃圾回收。如果它是局部变量,方法exit将做同样的事情。也就是说,如果您要求将成员显式设置为nil,我会质疑您的设计。 关于ruby-将对象设置为nil是否很常见?,我们在StackOverflow上找到一个类似的问题: https://

  7. ruby - 变量赋值后的 if 语句 - 有多常见? - 2

    我最近与一位同事讨论了以下Ruby语法:value=ifa==0"foo"elsifa>42"bar"else"fizz"end我个人并没有看到太多这种逻辑,但我的同事指出,这实际上是一种相当普遍的Rubyism。我试着用谷歌搜索这个主题,但没有找到任何文章、页面或SO问题来讨论它,这让我相信这可能是一种非常实际的技术。然而,另一位同事发现语法令人困惑,而是将上面的逻辑写成这样:ifa==0value="foo"elsifa>42value="bar"elsevalue="fizz"end缺点是value=的重复声明和隐式elsenil的丢失,如果我们想使用它的话。这也感觉它与Ruby

  8. ruby-on-rails - HTTParty 的内存问题和下载大文件 - 2

    这会导致Ruby出现内存问题吗?我知道如果大小超过10KB,Open-URI会写入TempFile。但是HTTParty会在写入TempFile之前尝试将整个PDF保存到内存吗?src=Tempfile.new("file.pdf")src.binmodesrc.writeHTTParty.get("large_file.pdf").parsed_response 最佳答案 您可以使用Net::HTTP。参见thedocumentation(特别是标题为“流媒体响应机构”的部分)。这是文档中的示例:uri=URI('http://e

  9. 常见网络安全产品汇总(私信发送思维导图) - 2

    安全产品安全网关类防火墙Firewall防火墙防火墙主要用于边界安全防护的权限控制和安全域的划分。防火墙•信息安全的防护系统,依照特定的规则,允许或是限制传输的数据通过。防火墙是一个由软件和硬件设备组合而成,在内外网之间、专网与公网之间的界面上构成的保护屏障。下一代防火墙•下一代防火墙,NextGenerationFirewall,简称NGFirewall,是一款可以全面应对应用层威胁的高性能防火墙,提供网络层应用层一体化安全防护。生产厂家•联想网御、CheckPoint、深信服、网康、天融信、华为、H3C等防火墙部署部署于内、外网编辑额,用于权限访问控制和安全域划分。UTM统一威胁管理(Un

  10. 关于Qt程序打包后运行库依赖的常见问题分析及解决方法 - 2

    目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'

随机推荐