Java之JVM、JUC面试题笔记(持续更新)

CountDownLatchCyclicBarrier

JUC 并发编程_juc并发编程-CSDN博客

java 类加载机制?如何实现自定义类加载器?findClass 与 loadClass 的区别?

在Java中,自定义类加载器通常是通过继承**java.lang.ClassLoader** 类并重写其findClass 方法来实现的,该方法首先调用从文件系统获取类的字节码,然后使用**defineClass** 方法将这些字节码转换成**Class** 对象实例。需要注意的是,loadClass 方法已经被**ClassLoader** 实现过了,它会首先尝试调用父类加载器来加载类,只有在父类加载器加载失败的情况下,才会调用**findClass**方法。

自定义类加载器:

java 复制代码
public class MyClassLoader extends ClassLoader{


    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String path="E:\\demo\\"+name+".class";
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            Files.copy(Paths.get(path),byteArrayOutputStream);

            //得到class文件的字节数组
            byte[] bytes = byteArrayOutputStream.toByteArray();
            // 调用defineClass将字节码转化为Class实例
            return defineClass(name,bytes,0,bytes.length);

        }catch (IOException e){
            e.printStackTrace();
            throw new ClassNotFoundException("类文件未找到",e);
        }
    }
}

注意:在Java中,一个类的身份不仅由其完整名字(包括包名)决定,还由加载它的类加载器决定。换句话说,即使两个类来自同一份字节码文件,如果它们被不同的类加载器实例加载,那么在JVM中,它们也会被视为不同的类。

java 复制代码
  MyClassLoader classLoader=new MyClassLoader();
        Class<?> aClass = classLoader.loadClass("Demo");
        Class<?> aClass1 = classLoader.loadClass("Demo");
        System.out.println(aClass==aClass1); //true

        MyClassLoader myClassLoader=new MyClassLoader();
        Class<?> aClass2 = myClassLoader.loadClass("Demo");
        System.out.println(aClass==aClass2); //false

loadClass方法

loadClass 是类加载的入口点。当你的代码尝试加载一个类时(通过**Class.forName** 、反射等方式),最终都会调用到类加载器的**loadClass** 方法。**loadClass**方法的主要职责是按照双亲委派模型来加载类:

  1. 检查类是否已加载 :首先检查这个类是否已经被加载过了。如果已加载,就直接返回该类的Class对象。这保证了每个类在JVM内部只有一个**Class**实例。
  2. 双亲委派 :如果类还没有被加载,**loadClass**会先委托给父类加载器尝试加载这个类。只有当父类加载器无法加载该类时(因为它不在父类加载器的搜索范围内),才会尝试自己加载。
  3. 调用findClass方法 :如果所有父类加载器都无法加载这个类,loadClass 方法最终会调用类加载器自己的**findClass**方法来加载这个类。

findClass方法

findClass 方法是**ClassLoader** 的一个受保护方法,它在类加载器的类加载机制中起到实际加载类的作用。当一个类加载器的父类加载器都无法加载某个类时,这个类加载器的**findClass**方法就会被调用。

栈会不会溢出?栈溢出一般抛什么异常?jvm 在哪里设置栈的大小?设置的参数是什
么?

如果线程请求分配的栈容量超过java虚拟机栈允许的最大容量的时候,java虚拟

机将抛出一个StackOverFlowError异常,可以通过命令行参数设置栈的大小,java -Xss512k Application,-Xms设置堆的初始大小,-Xmx设置堆的最大大小。

java 线程池?线程池构造函数的几个参数含义?keepAliveTime 解释一下?

java 复制代码
 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        3,  // 核心线程数量
        6,              //最大线程数
        60,             //空闲临时线程最大存活时间(数值)
        TimeUnit.SECONDS,//空闲临时线程最大存活时间(单位)
        new ArrayBlockingQueue<>(3),//任务队列,也就是一个堵塞队列,也可以使用LinkedBlockingQueue这个阻塞队列
        Executors.defaultThreadFactory(),//用线程池工具类Executors创建线程的工厂
        new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略中其中一个,丢弃任务并抛出RejectedExecutionException
    );

线程等待和唤醒的实现方式

  • Object 类下的 wait()、notify() 和 notifyAll() 方法;
  • Condition 类下的 await()、signal() 和 signalAll() 方法;
  • LockSupport 类下的 park() 和 unpark() 方法。

LockSupport 类的方法说明:

  1. LockSupport.park():休眠当前线程。
  2. LockSupport.unpark(线程对象):唤醒某一个指定的线程。

线程池拒绝策略

判断线程池中的任务已经全部执行完,等所有任务都执行完之后,进行数据的组装和返回

  1. 使用 CountDownLatch 或 CyclicBarrier 等待所有线程都执行完之后,再执行后续流程。

  2. CompletableFuture

java 复制代码
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 5, 2, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3));
        CompletableFuture<Void> a = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName());
        }, pool);
        CompletableFuture<Void> b = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName());
        }, pool);
        //等待两个线程执行完毕
        CompletableFuture.allOf(a,b).get();

ConcurrentHashMap为什么不允许插入Null

volatile有序性

死锁

解决方案:

  1. 按照顺序加锁:尝试让所有线程按照同一顺序获取锁,从而避免死锁。
  2. 设置获取锁的超时时间:尝试获取锁的线程在规定时间内没有获取到锁,就放弃获取锁,避免因为长时间等待锁而引起的死锁。

死锁排查工具:jconsole 和 JVisualVM:这些是 Java 自带的监视工具,可以用于监视线程、内存、CPU 使用率等信息,从而帮助排查死锁问题。

相关推荐
duration~34 分钟前
Maven随笔
java·maven
zmgst37 分钟前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
密码小丑1 小时前
11月4日(内网横向移动(一))
笔记
blammmp1 小时前
Java:数据结构-枚举
java·开发语言·数据结构
独行soc1 小时前
#渗透测试#SRC漏洞挖掘#深入挖掘XSS漏洞02之测试流程
web安全·面试·渗透测试·xss·漏洞挖掘·1024程序员节
暗黑起源喵1 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
鸭鸭梨吖1 小时前
产品经理笔记
笔记·产品经理
WaaTong2 小时前
Java反射
java·开发语言·反射
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试