谁是initiating loader

本文揭示并修正了《深入Java虚拟机》第二版中关于类加载器使用的一个常见误解,通过具体代码实例和ClassLoader.findLoadedClass()方法验证了实际加载过程与书中描述不符的情况。强调了阅读技术书籍时需审慎思考的重要性。
《深入Java虚拟机》第二版(很老的那本,Bill Venners写的,有中文翻译那本)第八章讲解类加载器用了个[url=http://www.artima.com/insidejvm/ed2/linkmod3.html]Cindy、Mom、Grandma的例子[/url]。但那个例子是错的。[url=http://mail.openjdk.java.net/pipermail/jdk6-dev/2011-October/002532.html]发了邮件到jdk6-dev邮件列表[/url],等待答复。顺便发这边大家讨论。

那个例子说,Cindy的parent是Mom,Mom的parent是Grandma,Grandma的parent是null也就是bootstrap class loader。
Cindy尝试加载java.io.FileReader会委派给Mom,Mom委派给Grandma,Grandma委派给bootstrap,bootstrap成功加载并一层层把Class返回出来。
这个过程完成后,书上说Cindy、Mom、Grandma都应该是initiating loader。但事实却不是如此。

代码例子:
[code]import java.io.*;
import java.net.*;

public class TestInitiatingLoader {
public static void main(String[] args) throws Exception {
Grandma grandma = new Grandma();
Mom mom = new Mom(grandma);
Cindy cindy = new Cindy(mom);
cindy.loadClass("Dummy").newInstance(); // force class init

final String reader = "java.io.FileReader";
printStats(grandma, reader); // false
printStats(mom, reader); // false
printStats(cindy, reader); // true
}

private static void printStats(LoadedClassQueryable loader, String name) {
System.out.printf("Is %s an initiating loader of %s: %b\n",
loader.getClass().getName(),
name,
loader.foundLoadedClass(name));
}
}

interface LoadedClassQueryable {
boolean foundLoadedClass(String name);
}

class Cindy
extends URLClassLoader
implements LoadedClassQueryable {
public Cindy(ClassLoader parent) {
super(makeArgs(), parent);
}

private static URL[] makeArgs() {
try {
return new URL[] { new File(".").toURI().toURL() };
} catch (Exception e) {
e.printStackTrace();
return new URL[] { };
}
}

@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if ("Dummy".equals(name)) {
// force Cindy to load this Dummy class
return findClass("Dummy");
}
return super.loadClass(name);
}

@Override
public boolean foundLoadedClass(String name) {
return findLoadedClass(name) != null;
}
}

class Mom
extends ClassLoader
implements LoadedClassQueryable {
public Mom(ClassLoader parent) {
super(parent);
}

@Override
public boolean foundLoadedClass(String name) {
return findLoadedClass(name) != null;
}
}

class Grandma
extends ClassLoader
implements LoadedClassQueryable {
public Grandma() {
super(null); // use bootstrap class loader as parent
}

@Override
public boolean foundLoadedClass(String name) {
return findLoadedClass(name) != null;
}
}[/code]
Dummy.java
[code]import java.io.*;

public class Dummy {
static {
// Dummy should be loaded by Cindy.
// So Cindy will be recorded as an initiating loader for java.io.FileReader
try {
new FileReader("Dummy.class").close();
} catch (Exception e) {
e.printStackTrace();
}
}
}[/code]

运行结果:
[code]Is Grandma an initiating loader of java.io.FileReader: false
Is Mom an initiating loader of java.io.FileReader: false
Is Cindy an initiating loader of java.io.FileReader: true[/code]

ClassLoader.findLoadedClass()可用于确认一个类与initiating loader关系。
[quote]findLoadedClass

protected final Class<?> findLoadedClass(String name)
Returns the class with the given binary name if this loader has been recorded by the Java virtual machine as an initiating loader of a class with that binary name. Otherwise null is returned.

Parameters:
name - The binary name of the class
Returns:
The Class object, or null if the class has not been loaded
Since:
1.1
[/quote]

读书要谨慎,切记不要人云亦云。
【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其与遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究与改进中。
ESP32 的远程服务发现(Remote Service Discovery)功能主要依赖于蓝牙低功耗(BLE)协议栈来实现。该机制允许设备在不建立完整连接的情况下,通过广播和扫描过程交换服务信息,从而识别彼此提供的服务类型和服务标识符等关键数据[^1]。 ### 工作原理 1. **广播与扫描**: - ESP32 设备可以作为广播者发送包含服务信息的数据包,也可以作为扫描者接收其他设备的广播信息。 - 广播数据包中通常包含服务 UUID(通用唯一识别码),这些 UUID 表示设备提供的特定服务,如心率监测、电池状态等。 - 扫描者可以通过解析接收到的广播数据包中的服务 UUID 来判断目标设备是否提供所需的服务。 2. **服务发现协议 (SDP)**: - 在 BLE 中,虽然没有像经典蓝牙那样完整的 SDP 协议,但通过 GATT(通用属性配置文件)服务和特征值来实现类似的功能。 - 当两个设备建立连接后,客户端设备可以发起服务发现请求,以获取服务器端设备上所有可用的服务及其特征值。 - 服务发现过程涉及多个 ATT(属性协议)命令和响应,包括 `Read By Group Type Request` 和 `Find Information Request` 等,用于遍历服务器上的服务和特征值。 3. **GATT 配置文件**: - GATT 是 BLE 中的核心配置文件之一,定义了如何通过属性协议传输数据。 - 每个服务由一个或多个特征值组成,每个特征值代表一种具体的数据类型。 - 客户端可以通过读取或写入特征值来与服务器进行交互,例如读取传感器数据或设置设备参数。 4. **调试与优化**: - 使用 ESP-IDF 开发环境时,开发者可以通过日志输出和调试工具监控服务发现过程中的关键事件和错误代码。 - 对于 BLE 应用程序,常见的调试方法包括使用 Wireshark 或蓝牙嗅探器捕获空中接口的数据包,分析广播数据、连接参数和服务发现请求/响应。 ### 示例代码 以下是一个简单的 ESP32 BLE 广播配置示例,展示了如何设置广播数据以包含服务 UUID: ```c #include "esp_gap_ble_api.h" #include "esp_gatt_common_api.h" // 设置广播数据 static uint8_t adv_data[] = { 0x02, 0x01, 0x06, // Flags: LE General Discoverable Mode 0x03, 0x03, 0x0A, 0x11 // Complete list of 16-bit service UUIDs }; void start_advertising() { esp_ble_gap_stop_advertising(); // 停止当前广播 // 配置广播参数 esp_ble_gap_set_device_name("ESP32_BLE"); esp_ble_gap_set_adv_data_raw(adv_data, sizeof(adv_data)); // 启动广播 esp_ble_gap_start_advertising(ESP_BLE_ADV_INDEFINITE); } ``` ### 相关问题 - 如何在 ESP32 上启用 BLE 广播并包含自定义服务 UUID? - ESP32 的 GATT 客户端如何发现远程设备的服务和特征值? - 蓝牙低功耗服务发现过程中可能出现哪些常见问题及解决办法?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值