成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

類(lèi)隔離自定義類(lèi)加載器實(shí)現(xiàn),你學(xué)會(huì)了嗎?

開(kāi)發(fā) 前端
本文分享的方式是從類(lèi)加載器方向出發(fā),實(shí)現(xiàn)最終的類(lèi)隔離,避免了不同模塊間不同類(lèi)的沖突,其中順便也簡(jiǎn)單帶過(guò)了jvm類(lèi)加載相關(guān)的知識(shí)點(diǎn),也算是一勞多得。

前言

由于微服務(wù)的快速迭代、持續(xù)集成等特性,越來(lái)越多的團(tuán)隊(duì)更傾向于它。但是也體現(xiàn)出了一些問(wèn)題,比如在基礎(chǔ)設(shè)施建設(shè)過(guò)程中,需要把通用功能下沉,把現(xiàn)有大而全的基礎(chǔ)設(shè)施按領(lǐng)域拆分,考慮需要兼容現(xiàn)有生產(chǎn)服務(wù),會(huì)產(chǎn)生不同的依賴(lài)版本,有時(shí)不注意就可以引發(fā)問(wèn)題。比如本文遇到的依賴(lài)包版本沖突問(wèn)題,以及如何利用類(lèi)隔離技術(shù)解決的分析。

類(lèi)隔離是什么?

類(lèi)隔離是一種通過(guò)類(lèi)加載器實(shí)現(xiàn)加載所需類(lèi)的實(shí)現(xiàn)方式,使得不同版本類(lèi)間隔離,避免了使用沖突問(wèn)題,最終的效果就是不同模塊的內(nèi)容被不同的類(lèi)加載器加載,滿(mǎn)足同一環(huán)境下同時(shí)兼容不同接口實(shí)現(xiàn)類(lèi)。

使用場(chǎng)景

比如業(yè)務(wù)服務(wù)A和業(yè)務(wù)服務(wù)B均需要消息通知等,均依賴(lài)消息中間件,但所引用版本不一致,導(dǎo)致最終只有一個(gè)版本加載到JVM,在某一個(gè)服務(wù)調(diào)用時(shí)會(huì)出現(xiàn) NoSuchMethodError或NoSuchClassError問(wèn)題,這就很難排查出來(lái),沒(méi)準(zhǔn)會(huì)影響項(xiàng)目進(jìn)度,最終月度的績(jī)效(“雞腿”)不保。

服務(wù)A pom.xml:

<!-- common-message-->
<dependency>
<groupId>com.lgy</groupId>
<artifactId>spring-common-message</artifactId>
<version>1.0.0<version>
</dependency>

服務(wù)B pom.xml:

<!-- common-message-->
<dependency>
<groupId>com.lgy</groupId>
<artifactId>spring-common-message</artifactId>
<version>2.0.0<version>
</dependency>

業(yè)務(wù)調(diào)用流程:

// 業(yè)務(wù)A調(diào)用微信服務(wù)通知
MessageUtil.sendMessage(content,peopleId,templateId,"wechat");
// 業(yè)務(wù)B調(diào)用微信服務(wù)通知
MessageUtil.sendToWechat(content,peopleId,templateId);

JVM最終加載的為 2.0.0 版本的依賴(lài),導(dǎo)致業(yè)務(wù)A在調(diào)用時(shí)拋異常java.lang.NoSuchMethodError。

解決方案

大體的解決思路就是,在不改變業(yè)務(wù)代碼的前提下, 業(yè)務(wù)A調(diào)用 1.0.0 版本的消息工具類(lèi), 業(yè)務(wù)B調(diào)用2.0.0版本的消息工具類(lèi),因此需要JVM能夠利用自定義類(lèi)加載器加載所需的類(lèi)或關(guān)聯(lián)的類(lèi)。

實(shí)現(xiàn)思路

  • 重寫(xiě)類(lèi)加載器,實(shí)現(xiàn)自定義類(lèi)加載(java.lang.ClassLoader)
  • 重寫(xiě)類(lèi)加載函數(shù)

重寫(xiě) findClass(String name)

重寫(xiě) loadClass(String name)

涉及的知識(shí)點(diǎn)

  • JVM加載過(guò)程:加載-》鏈接-》初始化(具體后續(xù)介紹)
  • 雙親委派機(jī)制:委托父加載器查詢(xún);如果父加載器查詢(xún)不到,則調(diào)用自身的findClass加載

重寫(xiě)findClass:

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class CustomerFindClass extends ClassLoader {
private Map<String, String> classPathMap = new HashMap<>();
public CustomerFindClass() {
// 業(yè)務(wù)A的自定義類(lèi)加載器
classPathMap.put("com.lgy.businessA.service.impl.MessageServiceImpl", "E:/dataway-demo/example/target/classes/com/lgy/businessA/service/impl/MessageServiceImpl.class");
classPathMap.put("com.lgy.v1.message.util.MessageUtil", "E:/dataway-demo/example/target/classes/com/lgy/v1/message/util/MessageUtil.class");
}

/**
* findClass方式加載類(lèi)
*/
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String classPath = classPathMap.get(name);
File file = new File(classPath);
if (!file.exists()) {
throw new ClassNotFoundException();
}
byte[] bytes = getClassData(file);
if (null == bytes || 0 == bytes.length) {
throw new ClassNotFoundException();
}
return defineClass(bytes, 0, bytes.length);
}

private byte[] getClassData(File file) {
try (InputStream ins = new FileInputStream(file);
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int bytesNumRead = 0;
while ((bytesNumRead = ins.read(buffer)) != -1) {
baos.write(buffer, 0, bytesNumRead);
}
return baos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return new byte[]{};
}

最終結(jié)果與預(yù)期的結(jié)果不一致:

  • 預(yù)期結(jié)果:業(yè)務(wù)A的MessageServiceImpl與MessageUtil由CustomerFindClass加載
  • 實(shí)際結(jié)果:業(yè)務(wù)A的MessageServiceImpl由CustomerFindClass加載,而MessageUtil由sun.misc.AppClassLoader加載。
  • 分析:由于JVM類(lèi)加載的雙親委托機(jī)制,業(yè)務(wù)A調(diào)用消息工具類(lèi)時(shí),類(lèi)加載器(CustomerFindClass)會(huì)委托父類(lèi)加載器(AppClassLoader)加載類(lèi),如果存在,則不再執(zhí)行自身的findClass方法加載,導(dǎo)致結(jié)果不理想。(main 方法類(lèi)默認(rèn)情況下都是由 JDK 自帶的 AppClassLoader 加載的)。

重寫(xiě)loadClass

private ClassLoader classLoader;

/**
* 重新loadClass方法
*/
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
Class result = null;
try {
//這里要使用 JDK 的類(lèi)加載器加載 java.lang 包里面的類(lèi)
result = classLoader.loadClass(name);
} catch (Exception e) {
// ignore error
}
if (null != result) {
return result;
}
String classPath = classPathMap.get(name);
File file = new File(classPath);
if (!file.exists()) {
throw new ClassNotFoundException();
}
byte[] bytes = getClassData(file);
if (null == bytes || 0 == bytes.length) {
throw new ClassNotFoundException();
}
return defineClass(bytes, 0, bytes.length);
}

滿(mǎn)足業(yè)務(wù)A的MessageServiceImpl與MessageUtil由CustomerFindClass加載

注意:這種方式破壞了雙親委托機(jī)制,但由于重寫(xiě)了loadClass方法,所有類(lèi)均會(huì)有CustomerFindClass加載器加載,需要過(guò)濾出不需要隔離的類(lèi),如java.lang包下的類(lèi),需要由ExtClassLoader 來(lái)加載。

總結(jié)

本文分享的方式是從類(lèi)加載器方向出發(fā),實(shí)現(xiàn)最終的類(lèi)隔離,避免了不同模塊間不同類(lèi)的沖突,其中順便也簡(jiǎn)單帶過(guò)了jvm類(lèi)加載相關(guān)的知識(shí)點(diǎn),也算是一勞多得。

責(zé)任編輯:武曉燕 來(lái)源: Java技術(shù)指北
相關(guān)推薦

2023-01-28 10:40:56

Java虛擬機(jī)代碼

2022-06-27 08:16:34

JSON格式序列化

2022-02-17 07:10:39

Nest自定義注解

2023-10-06 00:01:08

UML類(lèi)圖圖形

2024-11-27 11:07:20

vue計(jì)算屬性

2023-11-06 07:25:51

Spring配置應(yīng)用程序

2024-11-28 10:32:32

2024-07-29 10:35:44

KubernetesCSI存儲(chǔ)

2024-01-19 08:25:38

死鎖Java通信

2024-02-04 00:00:00

Effect數(shù)據(jù)組件

2023-07-26 13:11:21

ChatGPT平臺(tái)工具

2023-01-10 08:43:15

定義DDD架構(gòu)

2024-04-09 08:41:41

JVM類(lèi)加載Java

2022-06-16 07:50:35

數(shù)據(jù)結(jié)構(gòu)鏈表

2023-12-26 00:55:51

資源隔離CPU

2023-10-19 09:14:34

Java開(kāi)發(fā)

2022-01-20 07:31:49

架構(gòu)

2023-10-10 11:04:11

Rust難點(diǎn)內(nèi)存

2024-05-06 00:00:00

InnoDBView隔離

2024-07-31 08:39:45

Git命令暫存區(qū)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 黄色片免费在线观看 | 日本三级电影免费 | 草草视频在线播放 | 国产精品高潮呻吟久久av黑人 | a免费视频 | 久久精品一区二区 | 亚洲国产精品一区二区第一页 | 国产激情在线 | 一级黄色片日本 | 亚洲日韩欧美一区二区在线 | 日韩在线观看精品 | www.jizzjizz| 久久久www成人免费无遮挡大片 | 成人精品一区二区三区中文字幕 | 日韩一区二区福利视频 | 最新午夜综合福利视频 | 国产不卡视频 | 日本不卡一区二区三区在线观看 | 久夜精品| 欧美成年人视频在线观看 | 国产精品久久久久久吹潮 | 天天干夜夜操视频 | 日韩av免费在线观看 | 涩涩视频网站在线观看 | 龙珠z国语版在线观看 | 亚洲精品无 | 精品日本久久久久久久久久 | 亚州精品天堂中文字幕 | 在线亚洲电影 | 日本视频在线播放 | 91精品在线看 | 亚洲图片一区二区三区 | 一区二区三区av | 久久手机视频 | 日韩欧美在线观看 | 午夜在线精品偷拍 | 性色av一区 | 精品视频在线播放 | 在线观看日韩精品视频 | 亚洲 一区 | 国产日韩精品久久 |