当前位置: 首页 > news >正文

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

内存溢出(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,很有可能导致内存泄漏的发生。

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

    如上面这个伪代码,通过 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 = 41hs.add(cc);cc.setX(20);//hashCode = 51System.out.println("hs.remove = " + hs.remove(cc));//falsehs.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;@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + x;return result;}@Overridepublic 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 中的键。

相关文章:

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

内存溢出(OutofMemoryError) 简述 java doc 中对 Out Of Memory Error 的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存。 JVM 提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,由于 GC&…...

Linux 中断实验

目录 一、Linux 中断简介 上半部与下半部 二、添加设备树 三、编写驱动 1、定义宏 2、编写一个key结构体 3、imx6uirq设备添加成员 ​编辑4、按键中断处理函数 5、按键初始化 6、在驱动入口添加初始化 7、 驱动出口函数 代码如下 四、利用定时器进行消抖处理 1、添…...

【c++】指针

文章目录指针的定义和使用指针所占的内存空间空指针野指针const修饰指针指针和数组指针和函数指针、数组、函数案例:冒泡排序指针的定义和使用 指针定义的语法:数据类型 * 指针变量名 使用指针: 可以通过解引用的方式来找到指针指向的内存&…...

别具一格的婚礼,VR全景+婚礼的优势展现在哪里?

随着90后、95后逐渐步入结婚的主力军中,如何策划一场别具一格的婚礼是许多年轻人所头疼的,那么今年我们就可以玩点新潮的,VR婚礼或许是个不错的选择。 VR全景婚礼就是通过全景摄像机对婚礼进行记录,不但可以帮助新人捕捉婚礼的精彩…...

【GD32F427开发板试用】5. SPI驱动TFTLCD屏幕

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:hehung 之前发帖 【GD32F427开发板试用】1. 串口实现scanf输入控制LED 【GD32F427开发板试用】2. RT-Thread标准版移植 【GD32F427开发板试用…...

测试2年还拿实习生的薪资打发我,你后悔去吧····

20年7月大学毕业,学的计算机科学专业。因为考研之后,秋招结束了。没什么更多的岗位选择,就想找个工作先干着,然后亲戚在一家大厂公司上班说要招测试,所以就来做测试了。 虽然都是属于计算机大类,但自己专业…...

面向对象程序(C++)设计基础

一、类&对象C 在 C 语言的基础上增加了面向对象编程,C 支持面向对象程序设计。类是 C 的核心特性,通常被称为用户定义的类型。类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型…...

conda安装nodejs版本过低解决方法

conda命令直接安装nodejs时,可能会由于镜像源中nodejs版本过低导致没法安装高本版的nodejs,导致无法jupyterlab使用一些扩展插件。 解决方法如下:(windows环境下直接按提示下载版本安装就行,此处只介绍linux环境的解决…...

前端工程师leetcode算法面试必备-二分搜索算法(下)索算法(下)

一、287. 寻找重复数 给定一个包含 n 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。 1、HashMap 在没有其它附加条件的情况下&…...

使用Autowired为什么会被IDEA警告,应该怎么修改最佳

问题原因 关于这个问题,其实答案相对统一,实际上用大白话说起来也容易理解。 初始化问题 先看一下Java初始化类的顺序:父类的静态字段 > 父类静态代码块 > 子类静态字段 > 子类静态代码块 > 父类成员变量 > 父类构造代码块 &…...

面向对象(中)

面向对象(中) 一、 面向对象之继承性 继承性的好处 减少代码的冗余,提高了代码的复用性。 便于功能的扩展。 为多态性的使用,提供了前提。 继承性的格式 class A extends B{} A:子类、派生类、subclass B&#xff1a…...

【云原生】promehtheus整合grafana实现可视化监控实战

文章目录前言一. 实验环境二. 安装grafana2.1 grafana的介绍2.2 为什么选择grafana?2.3 grafana下载及安装三. 网页端配置grafana3.1 浏览器访问grafana网页3.2 使用grafana 获取prometheus的数据源3.3 grafana导入prometheus模板总结前言 大家好,又见面…...

Linux 内核定时器实验

目录 一、内核时间管理简介 二、内核定时器简介 三、驱动编写 1、修改makefile 2、添加定义 3、初始化led函数 4、添加调用 5、初始化定时器与定时器处理函数 这部分代码如下 四、ioctl函数 五、内核添加unlocked_ioctl 函数 1、添加设备操作集unlocked_ioctl成员 2…...

喜欢大屏电视?那就选择酷开系统,实现智能生活享受

随着科技的发展和我们生活水平的提高,越来越多的消费者开始认可并习惯使用各种高质量的科技产品,比如喜欢玩游戏的消费者,他们往往会追求流畅性更强、刷新率更快的大显示屏,以此获得更真实刺激的游戏体验,而喜欢追剧的…...

PMP应该如何备考?

备考之初的我们,总会四处搜索PMP备考经验,希望能拿到那些高分通关前辈的备考经验和方法。众所周知PMP考试因为有35个学时培训的基本要求,所以肯定是要通过培训机构报名的。 一,首先我们需要了解到新的考纲 1.PMP模块划分发生变化…...

AcWing《蓝桥杯集训·每日一题》—— 3956.截断数组

AcWing《蓝桥杯集训每日一题》—— 3956. 截断数组 文章目录AcWing《蓝桥杯集训每日一题》—— 3956. 截断数组一、题目二、解题思路三、代码实现本次博客我是通过Notion软件写的,转md文件可能不太美观,大家可以去我的博客中查看:北天的 BLOG…...

Docker的数据管理

一、管理docker容器中数据 管理Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器( DataVolumes Containers) 。 1、 数据卷 数据卷是一个供容器使用的特殊目录,位于容器中。可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻…...

RxJS处理异步数据流

什么是异步? 异步(Asynchronous)指的是不同步发生的事件或操作。通常,同步操作是指一系列代码按照顺序依次执行,直到当前代码块执行完毕后才继续执行下一个代码块;而异步操作则是指某些代码会被提交到后台执行&#…...

IP地址与用户行为

IP地址能够解决网络风险和提高网络安全的原因是:所有的网络请求都会带有IP信息,是访问者的独立标识,另外ip地址的分配和管理比较严格,难以造假。另外ip属于网络层,可以轻松的对其进行阻断。现有的各种网络安全、负载均…...

底层逻辑2

有些创业者,在3D打印⽕爆的时候做3D打印,在VR(虚拟现 实)蓬勃发展的时候转⾏做VR,在区块链成为热⻔话题的时候摇身⼀ 变成了区块链专家,⽽⼈⼯智能⽕了以后,他们⼜全身⼼投⼊⼈⼯智 能这⼀⾏。再…...

TCP报头详解及TCP十种核心机制(一)

目录 前言: TCP报头 TCP核心机制 一、确认应答 二、超时重传 小结: 前言: 这篇文章详细介绍了TCP报头中的一些核心数据,及两种TCP核心机制。其他的一些机制会在后面文章中详细介绍。 TCP报头 解释: 1&#xff…...

Linux用户的添加、修改和删除以及相关配置文件:useradd、passwd、usermod、userdel、相关配置文件

目录 账户的创建(useradd) 第一步:创建账号 第二步:创建密码 useradd参考文件 CROUP100 HOME/home INACTIVE-1 EXPIRE SHELL/bin/bash SKEL/etc/skel UID/GID密码参数参考:/etc/login.defs 密码参数显示命…...

进程地址空间

目录 回顾C/C语言的程序地址空间 感性认识虚拟地址空间 虚拟地址空间与物理空间如何建立映射关系 为什么要虚拟地址空间? 回顾C/C语言的程序地址空间 在学习C/C语言时我们知道了一个概念叫程序地址空间。通俗来说就是如下一张表,从中可以得知系统的几…...

数楼梯(加强版)

数楼梯(加强版) 题目背景: 小明一天放学回家,看到从1楼到2楼共有n个台阶,因为好奇,他想尝试一下总共有几种方案到二楼?他可以1步,2步,3步的跳,不能跳3步以上. 他试了很多次都没有解决这个问题,于是请求聪明的你帮忙解决这个问题. 题目描述: 1楼到2楼楼梯有n级台阶。小明每…...

MySQL-数据类型

数据类型简介数据表由多列字段构成,每一个字段指定了不同的数据类型,指定了数据类型之后,也就决定了向字段插入的数据内容。不同的数据类型也决定了 MySQL 在存储它们的时候使用的方式,以及在使用它们的时候选择什么运算符号进行运…...

剑指 Offer 32 - II. 从上到下打印二叉树 II(java解题)

剑指 Offer 32 - II. 从上到下打印二叉树 II(java解题)1. 题目2. 解题思路3. 数据类型功能函数总结4. java代码5. 踩坑记录1. 题目 从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。 例如: 给定二叉…...

C#网络爬虫开发

1前言爬虫一般都是用Python来写,生态丰富,动态语言开发速度快,调试也很方便但是我要说但是,动态语言也有其局限性,笔者作为老爬虫带师,几乎各种语言都搞过,现在这个任务并不复杂,用我…...

Fastjson 总结

0x00 前言 这一篇主要是针对已经完成的fastjson系列做一个知识点总结,一来是为了更加有条理的梳理已经存在的内容,二来是为了更好的复习和利用。 0x01 Fastjson基础知识点 1.常见问题: 问:fastjson的触发点是什么?…...

文件路径模块os.path

文件路径模块os.path 文章目录文件路径模块os.path1.概述2.解析路径2.1.拆分路径和文件名split2.2.获取文件名称basename2.3.返回路径第一部分dirname2.4.扩展名称解析路径splitext2.5.返回公共前缀路径commonprefix3.创建路径3.1.拼接路径join3.2.获取家目录3.3.规范化路径nor…...

Kerberos简单介绍及使用

Kerberos作用 简单来说安全相关一般涉及以下方面:用户认证(Kerberos的作用)、用户授权、用户管理.。而Kerberos功能是用户认证,通俗来说解决了证明A是A 的问题。 认证过程(时序图) 核心角色/概念 KDC&…...

天河做网站技术/天津seo关键词排名优化

最近有小伙伴来问,BarTender 2016能不能导出模板为pdf文件?这个是可以的,之前针对BarTender 10.1就介绍过一种方法了。本文,小编再针对BarTender 2016给大家讲下如何导出标签模板为pdf文件? 1、在BarTender 2016中设计…...

可靠的专业网站建设平台/学生个人网页制作

最近项目中用到PostgreSQL,需要在服务器上安装,记录一下安装过程,便于日后查阅。 一、环境准备 本次安装的 PostgreSQL 版本是 11.4,Centos是7.6,其他的没什么了。 二、部署安装 首先需要配置一些必要的环境&#…...

wordpress 后台设置/万网官网域名查询

2018年南开大学物理保研夏令营通知导读:南开大学物理2018年保研夏令营通知已经公布,宣讲及面试活动时间为4月27日(周四)上午8:00-12:00。具体内容请看如下信息,想了解更多相关信息请持续关注我们应届毕业生考试网!为方便广大2018届优秀应届本…...

wordpress设置缓存/淘宝运营培训班学费大概多少

我们以Android获取TP报点为例,分析poll过程。poll系统调用功能是检测设备是否有可读等对应事件发生时,调用read系统调用实现对设备的无阻塞访问。现在我们来分析poll的基本调用流程。 首先看应用如何使用poll: int main(int argc, char* argv[]) {int …...

网站建设营销话术/青岛seo代理计费

2019独角兽企业重金招聘Python工程师标准>>> 根据《深入浅出设计模式(C#/Java版)》所述, Strategy模式的应用场景是:1. 多个类的分别只是在于行为不同2. 你需要对行为的算法做很多变动3. 客户不知道算法要使用的数据 Template Method模式的应用场景是:1. 你想将相同…...

wordpress主题可以更改主页布局/网络营销的推广

createWriteStream是Node.js中的一个方法,可以用来创建一个可写流。可写流是一种用于写入数据的流。它允许我们在不断写入数据的同时将数据写入文件或其他目标。可写流是流的一种,流是Node.js中的一种抽象概念,表示一个数据流的生成器。可写流…...