我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Java实战之OutOfMemoryError异常问题及解决方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Java实战之OutOfMemoryError异常问题及解决方法

在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError (下文称OOM)异常的可能。本篇主要结合着【深入理解Java虚拟机】一书当中整理了本篇博客,感兴趣的跟着小编一块来学习呀!

本篇文章和上一篇写到的 Java内存区域划分 息息相关,如果您对Java内存区域划分不是很了解,建议了解一下,不然这篇文章读起来会很痛苦。。。

一、简言

本节内容的目的有两个:

  • 第一,通过代码验证Java虚拟机规范中描述的各个运行时区域储存的内容;
  • 第二,希望读者在工作中遇到实际的内存溢出异常时,能根据异常的信息快速判断是哪个区域的内存溢出,知道怎样的代码可能会导致这些区域的内存溢出,以及出现这些异常后该如何处理。

下面代码的开头都注释了执行时所需要设置的虚拟机启动参数(注释中“VM Args”后面跟着的参数),这些参数对实验的结果有直接影响,请读者调试代码的时候不要忽略掉。(本篇文章所有案例都采用了JDK1.8版本进行测试)

如果读者使用控制台命令来执行程序,那直接跟在Java命令之后书写就可以。如果读者使用Eclipse IDE,可以在Debug/Run页签中的设置。

二、代码实战

1、Java堆溢出

Java堆用于储存对象实例,我们只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量到达最大堆的容量限制后产生内存溢出异常。

将Java堆设置大小为20MB,不可扩展(将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数-XX:+HeapDumpOnOutOfMemoryError 可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析(内存堆转储快照 指的是溢出后,内存当中的对象占用情况)。

我用的是ider:

设置启动参数:
Xms:最小堆内存 Xmx:最大可扩展内存
XX:+HeapDumpOnOutOfMemoryError:可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

import java.util.ArrayList;
import java.util.List;
public class HeapOOM {
    static class OOMObject{
    }
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();
        while (true){
            list.add(new OOMObject());
        }
}

运行结果:

因为设置了-XX:+HeapDumpOnOutOfMemoryError参数,所以生成了 这个报告。可以查看对象占用内存。

Java堆内存的OOM异常是实际应用中最常见的内存溢出异常情况。出现Java堆内存溢出时,异常堆栈信息"java.lang.OutOfMemoryError”会跟着进一步提示“Java heapspace"。

要解决这个区域的异常,一般的手段是首先通过内存映像分析工具(如EclipseMemory Analyzer、Dier的jprofiler)对dump出来的堆转储快照进行分析,重点是确认内存中的对象是否是必要的,也就是要先分清楚到底是出现了内存泄漏(Memory Leak)还是内存溢出(Memory Overflow)。

如果是内存泄漏,可进一步通过工具查看泄漏对象到GC Roots的引用链。于是就能找到泄漏对象是通过怎样的路径与GC Roots相关联并导致垃圾收集器无法自动回收它们的。掌握了泄漏对象的类型信息,以及GC Roots引用链的信息,就可以比较准确地定位出泄漏代码的位置。

如果不存在泄漏,换句话说就是内存中的对象确实都还必须存活着,那就应当检查虚拟机的堆参数(-Xmx与-Xms),与机器物理内存对比看是否还可以调大,从代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况,尝试减少程序运行期的内存消耗。

后面我会专门写一篇关于内存分析工具的博客,XX:+HeapDumpOnOutOfMemoryError这个只是有内存占用情况,工具可以帮我们看到对象的引用链情况。

2、虚拟机栈和本地方法栈溢出

由于在HotSpot虚拟机中并不区分虚拟机栈和本地方法栈,因此对于HotSpot来说,-Xoss参数(设置本地方法栈大小)虽然存在,但实际上是无效的,栈容量只由-Xss参数设定。关于虚拟机栈和本地方法栈,在Java虚拟机规范中描述了两种异常。
注意:HotSpot虚拟机的栈容量是不可以动态扩展的。

  • 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
  • 允许栈空间动态扩展时,当扩展时无法申请到足够的内存时会抛出OutOfMemoryError异常
public class JavaVMStackSOF {
    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) {
        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Throwable e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}
  1. 当声明是基本类型的变量的时,其变量名及值(变量名及值是两个概念)是放在JAVA虚拟机栈中
  2. 当声明的是引用变量时,所声明的变量(该变量实际上是在方法中存储的是内存地址值)是放在JAVA虚拟机的栈中,该变量所指向的对象是放在堆类存中的。

实验结果表明:在单个线程下,无论是由于栈帧太大,还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是StackOverflowError异常。换成远古时代的Classic虚拟机,这款虚拟机可以支持动态扩展 栈内存的容量,这时候就会报StackOverflowError异常了。

也就是当我设置-Xss128k和不设置都是报同样的错误,并没有出现内存溢出异常,原因就是 HotSpot虚拟机的栈容量是不可以动态扩展的,但是值得注意的是我的电脑是16G运行内存的,当我设置-Xss128k的时候输出的长度是将近1000,当我不限制-Xss128k大小的时候输出的长度是20000左右,也就意味着每个线程的栈帧大小默认最大是2MB

如果测试时不限于单线程,通过不断地建立线程的方式倒是可以产生内存溢出异常,在这种情况下,给每个线程的栈分配的内存越大,反而越容易产生内存溢出异常。

原因其实不难理解,操作系统分配给每个进程的内存是有限制的,譬如32位Windows的单个进程 最大内存限制为2GB。HotSpot虚拟机提供了参数可以控制Java堆和方法区这两部分的内存的最大值。那么虚拟机栈和本地方法栈内存如下:

虚拟机栈和本地方法栈内存=2GB-最大堆容量-最大方法区容量-程序计数器容量

因此为每个线程分配到的栈内存越大,可以建立的线程数量自 然就越少,建立线程时就越容易把剩下的内存耗尽。

通过上面了解到,出现StackOverflowError异常时有错误堆栈可以阅读,相对来说,比较容易找到问题的所在(一般出现死循环可能会导致)。

如果是建立过多线程导致的内存溢出,而不是栈溢出,在不能减少线程数或者更换64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。如果没有这方面的经验,这种通过“减少内存”的手段来解决内存溢出的方式会比较难以想到。

public class JavaVMStackOOM {
    private void dontStop(){
        while (true){

        }
    }

    public void stackLeakByThread(){
        while (true){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();
                }
            });
            thread.start();
        }
    }

    public static void main(String[] args) {
        JavaVMStackOOM oom = new JavaVMStackOOM();
        oom.stackLeakByThread();
    }
}

注意 重点提示一下,如果读者要尝试运行上面这段代码,记得要先保存当前的工作,由于在 Windows平台的虚拟机中,Java的线程是映射到操作系统的内核线程上,无限制地创建线程会对操 作系统带来很大压力,上述代码执行时有很高的风险,可能会由于创建线程数量过多而导致操作系统 假死(电脑可能直接死机)。

在32位操作系统下的运行结果:
原因:32位有进程大小内存限制。

Exception in thread "main" java.lang.OutOfMemoryError: unable to create native thread

注意:如果要测试上面内存溢出代码,记住先保存当前的工作,避免电脑卡死带来的麻烦。

3、运行时常量池溢出

由于运行时常量池是方法区的一部分,所以这两个区域的溢出测试可以放到一起进行。前面曾经 提到HotSpot从JDK 7开始逐步“去永久代”的计划,并在JDK 8中完全使用元空间来代替永久代,在此我们就以测试代码来观察一下,使用“永久代”还是“元空间”来实现方法区,对程序有什么 实际的影响。

String::intern()是一个本地方法,它的作用是如果字符串常量池中已经包含一个等于此String对象的 字符串,则返回代表池中这个字符串的String对象的引用否则,会将此String对象包含的字符串添加 到常量池中,并且返回此String对象的引用

import java.util.ArrayList;
import java.util.List;

public class RuntimeConstantPoolOOM {
    public static void main(String[] args) {
        // 使用List保持着常量池引用,避免Full GC回收常量池行为
        List<String> list = new ArrayList<>();
        // 10MB的PerSize在integer范围内足够产生00M
        int i = 0;
        while (true){
            list.add(String.valueOf(i++).intern());
        }
    }
}
  • JDK7及以前(了解):-XX:PermSize设置永久代初始大小。-XX:MaxPermSize设置永久代最大可分配空间。(JDK7目前已经很少用了,这两个参数在JDK8及以后已经没有了,所以不必掌握,了解一下)
  • JDK8及以后:可以使用-XX:MetaspaceSize和-XX:MaxMetaspaceSize设置元空间初始大小以及最大可分配大小。

使用JDK 7或更高版本的JDK来运行这段程序并不会得到相同的结果,无论是在JDK 7中继续使 用-XX:MaxPermSize参数或者在JDK 8及以上版本使用-XX:MaxMeta-spaceSize参数把方法区容量同 样限制在6MB,都不会出现溢出异常,循环将一直进行下去,永不停歇。出现这种变 化,是因为自JDK 7起,原本存放在永久代的字符串常量池被移至Java堆之中,所以在JDK 7及以上版 本,限制方法区的容量对该测试用例来说是毫无意义的

在JDK1.7中(包括1.7以上)常量池存储的不再是对象,而是对象引用,真正的对象是存储在堆中的。把RuntimeConstantPoolOOM.java运行时的VM参数改为如下(设置堆大小)所示:

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

运行结果:

查看生成的堆内存快照:

4、方法区溢出

方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。对于这个区域的测试,基本的思路是运行时产生大量的类去填满方法区,直到溢出。虽然直接使用Java SE API也可以动态产生类(如反射时的GeneratedConstructorAccessor 和动态代理等),但在本次实验中操作起来比较麻烦。借助CGLib直接操作字节码运行时,生成了大量的动态类。

值得特别注意的是,我们在这个例子中模拟的场景并非纯粹是一个实验,这样的应用经常会出现在实际应用中:当前的很多主流框架,如Spring和Hibernate对类进行增强时,都会使用到CGLib这类字节码技术,增强的类越多,就需要越大的方法区来保证动态生成的Class可以加载人内存

测试示例:

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class JavaMethodAreaOOM {
    public static void main(String[] args) {
        while (true) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(OOMObject.class);
            enhancer.setUseCache(false);
            enhancer.setCallback(new MethodInterceptor() {
                @Override
                public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                    return proxy.invokeSuper(obj, args);
                }
            });
            enhancer.create();
        }
    }

    static class OOMObject {
    }
}

设置元空间最大空间,和初始化空间参数:
类信息是都存在方法区的,方法区在jdk1.8将永久区改为了元空间。自此以后,常量池在元空间都是存储的引用。实际对象是在堆中。

-XX:MaxMetaspaceSize=10m -XX:MetaspaceSize=10m

运行结果:

方法区溢出也是一种常见的内存溢出异常,一个类如果要被垃圾收集器回收,要达成的条件是比 较苛刻的。在经常运行时生成大量动态类的应用场景里,就应该特别关注这些类的回收状况。这类场 景除了之前提到的程序使用了CGLib字节码增强和动态语言外,常见的还有:大量JSP或动态产生JSP 文件的应用(JSP第一次运行时需要编译为Java类)、基于OSGi的应用(即使是同一个类文件,被不同 的加载器加载也会视为不同的类)等。

5、本机直接内存溢出

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中 定义的内存区域。但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现。

直接内存:可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用`进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据(但是有一点注意,虽然不占用堆内存,但是他占用了服务器内存)。

直接内存(Direct Memory)的容量大小可通过-XX:MaxDirectMemorySize参数来指定,如果不 去指定,则默认与Java堆最大值(由-Xmx指定)一致。

代码示例:

越过了DirectByteBuffer类直接通 过反射获取Unsafe实例进行内存分配Unsafe类的getUnsafe()方法指定只有引导类加载器才会返回实 例,体现了设计者希望只有虚拟机标准类库里面的类才能使用Unsafe的功能,在JDK 10时才将Unsafe 的部分功能通过VarHandle开放给外部使用),因为虽然使用DirectByteBuffer分配内存也会抛出内存溢 出异常,但它抛出异常时并没有真正向操作系统申请分配内存,而是通过计算得知内存无法分配就会 在代码里手动抛出溢出异常,真正申请分配内存的方法是Unsafe::allocateMemory()

import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class DirectMemoryOOM {
    private static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredFields()[0];
        unsafeField.setAccessible(true);
        Unsafe unsafe = (Unsafe) unsafeField.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
        }
    }
}

运行参数:

-Xmx20M -XX:MaxDirectMemorySize=10M -XX:+HeapDumpOnOutOfMemoryError

运行结果:

我设置了-XX:+HeapDumpOnOutOfMemoryError发现运行完成之后并没有发现有内存快照。

由直接内存导致的内存溢出,一个明显的特征是在Heap Dump文件中不会看见有什么明显的异常 情况,如果读者发现内存溢出之后产生的Dump文件很小,而程序中又直接或间接使用了 DirectMemory(典型的间接使用就是NIO),那就可以考虑重点检查一下直接内存方面的原因了。

三、JVM常用的启动参数

堆:

  • -Xms3550m:设置JVM初始内存为3550M。表示初始化JAVA堆的大小及该进程刚创建出来的时候,他的专属JAVA堆的大小,一旦对象容量超过了JAVA堆的初始容量,JAVA堆将会自动扩容到-Xmx大小。
  • -Xmx3550m:设置JVM最大可用内存为3550M。表示java堆可以扩展到的最大值,在很多情况下,通常将-Xms和-Xmx设置成一样的,因为当堆不够用而发生扩容时,会发生内存抖动影响程序运行时的稳定性。

栈:

  • -Xss128k:规定了每个线程虚拟机栈及堆栈的大小,一般情况下,256k是足够的,此配置将会影响此进程中并发线程数的大小(和堆是不一样的,不支持动态扩展)。

方法区:

  • JDK7及以前(了解):-XX:PermSize设置永久代初始大小。
  • -XX:MaxPermSize设置永久代最大可分配空间。(JDK7目前已经很少用了,这两个参数在JDK8及以后已经没有了,所以不必掌握,了解一下)-XX:MaxMetaspaceSize=10m:设置元空间最大值,默认是-1,即不限制,或者说只受限于本地内存 大小。
  • -XX:MetaspaceSize=10m:指定元空间的初始空间大小,以字节为单位,达到该值就会触发垃圾收集 进行类型卸载,同时收集器会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放 了很少的空间,那么在不超过-XX:MaxMetaspaceSize(如果设置了的话)的情况下,适当提高该值。
  • -XX:MinMetaspaceFreeRatio:作用是在垃圾收集之后控制最小的元空间剩余容量的百分比,可 减少因为元空间不足导致的垃圾收集的频率。类似的还有-XX:Max-MetaspaceFreeRatio,用于控制最 大的元空间剩余容量的百分比。

内存:

  • -XX:+HeapDumpOnOutOfMemoryError 可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析(内存堆转储快照 指的是溢出后,内存当中的对象占用情况)

GC:

  • -XX:-PrintGCDetails:每次GC时打印详细信息。

四、面试题

public static void main(String[] args) {
    String str1 = new StringBuilder("计算机").append("软件").toString();
    System.out.println(str1.intern() == str1);
    String str2 = new StringBuilder("ja").append("va").toString();
    System.out.println(str2.intern() == str2);
}

这段代码在JDK 6中运行,会得到两个false,而在JDK 7中运行,会得到一个true和一个false。在jdk1.8运行也是,true、false。

产 生差异的原因是,在JDK 6中,intern()方法会把首次遇到的字符串实例复制到永久代的字符串常量池 中存储,返回的也是永久代里面这个字符串实例的引用,而由StringBuilder创建的字符串对象实例在 Java堆上,所以必然不可能是同一个引用,结果将返回false。

而JDK 7(以及部分其他虚拟机,例如JRockit)的intern()方法实现就不需要再拷贝字符串的实例 到永久代了,既然字符串常量池已经移到Java堆中,那只需要在常量池里记录一下首次出现的实例引 用即可,因此intern()返回的引用和由StringBuilder创建的那个字符串实例就是同一个。
而对str2比较返 回false,这是因为“java”这个字符串在执行String-Builder.toString()之前就已经出现过了,字符串常量 池中已经有它的引用,不符合intern()方法要求“首次遇到”的原则,“计算机软件”这个字符串则是首次 出现的,因此结果返回true。(这块说实话不好理解,说白了就是java是个特殊的字符串,他在常量池里面就一直存在)

总结:在1.8之后通过intern()添加到常量池,只有字符串在常量池不存在的时候才会返回字符串的引用。

五、总结

到此为止,我们明白了虚拟机里面的内存是如何划分的,哪部分区域、什么样的代码和操作可能 导致内存溢出异常。虽然Java有垃圾收集机制,但内存溢出异常离我们并不遥远,本章只是讲解了各 个区域出现内存溢出异常的原因,下一章将详细讲解Java垃圾收集机制为了避免出现内存溢出异常都 做了哪些努力。

到此这篇关于Java实战之OutOfMemoryError异常的文章就介绍到这了,更多相关java  OutOfMemoryError异常内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Java实战之OutOfMemoryError异常问题及解决方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

解决UnsupportedOperationException异常问题的方法

本篇文章和大家了解一下解决UnsupportedOperationException异常问题的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。目录UnsupportedOperationException异常下面开始正
2023-07-06

基于java.lang.IllegalArgumentException异常报错问题及解决方法

java.lang.IllegalArgumentException是Java中的一个异常类,表示方法的参数不合法。当方法的参数不满足方法定义的要求时,就会抛出该异常。下面是一些可能导致该异常的情况以及解决方法:1. 参数为空:如果方法要求
2023-08-15

Python中异常处理的常见问题及解决方法

Python中异常处理的常见问题及解决方法引言:在编写程序时,很难避免出现各种各样的错误和异常。异常处理是一种机制,可以在程序运行时捕获和处理这些异常,从而保证程序的稳定性和可靠性。在Python中,异常处理是一项非常重要的技能,本文将介绍
2023-10-22

WCF常见异常问题的解决方法

这篇文章主要讲解了“WCF常见异常问题的解决方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“WCF常见异常问题的解决方法”吧!WCF还是比较常用的,于是我研究了一下WCF,在这里拿出来和大
2023-06-17

ResponseBodyAdvice常见问题及解决方法

这篇文章主要讲解了“ResponseBodyAdvice常见问题及解决方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ResponseBodyAdvice常见问题及解决方法”吧!场景通过R
2023-06-20

打包异常解决办法之HTTPS证书问题

当打包应用程序时,可能会遇到HTTPS证书问题。这可能是由于应用程序尝试与受信任的HTTPS服务器建立安全连接时,无法验证服务器的证书引起的。以下是解决此问题的一些办法:1. 确保服务器证书是有效的:检查服务器证书是否过期或由于其他原因无效
2023-09-21

Nacos的常见问题及解决方法

本篇内容主要讲解“Nacos的常见问题及解决方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Nacos的常见问题及解决方法”吧!如何依赖最新的 Nacos 客户端?很多用户都是通过 Sprin
2023-06-02

C++中常见的异常处理问题解决方法

C++中常见的异常处理问题解决方法,需要具体代码示例引言:在编写C++程序时,时常会遇到程序出现异常的情况,如除数为0、数组越界、空指针访问等等。这些异常会导致程序的崩溃或者产生不可预测的结果,为了增强程序的稳定性和可靠性,我们需要使用异常
2023-10-22

亚马逊服务器异常问题解决方法

1.了解服务器异常的原因在解决服务器异常问题之前,我们需要了解服务器异常的原因。服务器异常可能是由于硬件故障、软件问题、网络问题或者其他原因引起的。因此,我们需要对服务器进行全面的诊断,以确定问题的根本原因。2.使用亚马逊提供的工具进行故障排除亚马逊提供了一系列工具,可以帮助我们诊断和解决服务器异常问题。其中包括:AmazonCloudWatch:可以监控服务器的性能指标,如CPU使用率、内存使用率、网络流量等,以...
2023-10-27

Java中java.lang.ClassCastException异常原因以及解决方法详解

Java中的java.lang.ClassCastException异常发生在尝试将对象强制转换为不兼容类型时。原因包括类型转换错误、对象类型不匹配、向下转型失败和对象类型不兼容。解决方法包括识别异常点、检查类型安全、使用instanceof运算符、避免向下转型、处置空值、使用反射和检查泛型类型。避免强制转换,改用更安全的类型转换方法,例如instanceof运算符和反射。
Java中java.lang.ClassCastException异常原因以及解决方法详解
2024-04-02

Redis常见的几个问题及解决方法

本篇内容主要讲解“Redis常见的几个问题及解决方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Redis常见的几个问题及解决方法”吧! 1、如何保证Redis高可用和高并发?Redis主从架
2023-06-16

@ConfigurationProperties使用时常见问题及解决方法

这篇文章主要介绍“@ConfigurationProperties使用时常见问题及解决方法”,在日常操作中,相信很多人在@ConfigurationProperties使用时常见问题及解决方法问题上存在疑惑,小编查阅了各式资料,整理出简单好
2023-06-20

MySQL SSL 连接常见问题及解决方法

MySQL SSL 连接常见问题及解决方法概述:Secure Socket Layer(SSL)是一种加密传输协议,用于保护数据在网络上的传输安全。MySQL 支持通过 SSL 连接数据库服务器,以增强数据的保密性和完整性。然而,在使用 M
2023-10-22

C++多态性的实现及常见问题解决方法

C++多态性的实现及常见问题解决方法引言:在C++编程中,多态性是一种重要的概念和特性。它允许我们使用基类的指针或引用来操作派生类的对象,从而实现了程序的灵活性和复用性。本文将介绍C++中多态性的实现方式,并探讨一些常见的多态性问题及其解决
2023-10-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录