本文目录导读:

我来为您提供一个全面的Java类加载器案例,包括基本概念演示、自定义类加载器实现以及应用场景。
基础类加载器演示
import java.net.URL;
import java.net.URLClassLoader;
/**
* 类加载器基础案例
*/
public class ClassLoaderBasicDemo {
public static void main(String[] args) throws Exception {
// 获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("系统类加载器: " + systemClassLoader);
// 获取扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println("扩展类加载器: " + parent);
// 获取引导类加载器(通常为null)
ClassLoader bootstrap = parent.getParent();
System.out.println("引导类加载器: " + bootstrap);
// 查看类的加载器
Class<?> stringClass = String.class;
System.out.println("String类加载器: " + stringClass.getClassLoader());
Class<?> demoClass = ClassLoaderBasicDemo.class;
System.out.println("Demo类加载器: " + demoClass.getClassLoader());
// 查看类加载器的加载路径
URL[] urls = ((URLClassLoader) systemClassLoader).getURLs();
System.out.println("\n系统类加载器加载路径:");
for (URL url : urls) {
System.out.println(" - " + url);
}
}
}
自定义类加载器
import java.io.*;
import java.nio.file.*;
import java.security.MessageDigest;
/**
* 自定义类加载器 - 支持加密解密
*/
public class CustomClassLoader extends ClassLoader {
private final String classPath;
private final String encryptionKey; // 简单示例,实际应该使用更安全的方式
public CustomClassLoader(String classPath, String encryptionKey) {
this.classPath = classPath;
this.encryptionKey = encryptionKey;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// 将点号转成路径分隔符
String path = name.replace('.', '/').concat(".class");
File file = new File(classPath, path);
if (!file.exists()) {
throw new ClassNotFoundException("类文件不存在: " + name);
}
try {
byte[] classBytes = loadClassData(file);
// 解密类字节码
classBytes = decrypt(classBytes, encryptionKey);
// 定义类
return defineClass(name, classBytes, 0, classBytes.length);
} catch (Exception e) {
throw new ClassNotFoundException("加载类失败: " + name, e);
}
}
/**
* 加载class文件字节码
*/
private byte[] loadClassData(File file) throws IOException {
try (FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
return bos.toByteArray();
}
}
/**
* 简单的XOR加密/解密
*/
private byte[] decrypt(byte[] data, String key) {
byte[] keyBytes = key.getBytes();
byte[] result = new byte[data.length];
for (int i = 0; i < data.length; i++) {
result[i] = (byte) (data[i] ^ keyBytes[i % keyBytes.length]);
}
return result;
}
/**
* 加密class文件
*/
public static void encryptClassFile(File sourceFile, File targetFile, String key)
throws IOException {
byte[] classData = Files.readAllBytes(sourceFile.toPath());
byte[] encryptedData = new byte[classData.length];
byte[] keyBytes = key.getBytes();
for (int i = 0; i < classData.length; i++) {
encryptedData[i] = (byte) (classData[i] ^ keyBytes[i % keyBytes.length]);
}
Files.write(targetFile.toPath(), encryptedData);
System.out.println("加密完成: " + targetFile.getPath());
}
}
热部署类加载器
import java.io.*;
import java.net.*;
import java.util.*;
/**
* 支持热部署的类加载器
*/
public class HotDeployClassLoader extends URLClassLoader {
private final String className;
private final String classPath;
private Map<String, Long> classModifiedTimes = new HashMap<>();
public HotDeployClassLoader(String className, String classPath) {
super(new URL[0], HotDeployClassLoader.class.getClassLoader());
this.className = className;
this.classPath = classPath;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// 只负责加载指定的类及其依赖
if (!name.equals(className)) {
return super.findClass(name);
}
try {
String path = name.replace('.', '/').concat(".class");
File file = new File(classPath, path);
if (!file.exists()) {
throw new ClassNotFoundException("类文件不存在: " + name);
}
byte[] classData = Files.readAllBytes(file.toPath());
return defineClass(name, classData, 0, classData.length);
} catch (IOException e) {
throw new ClassNotFoundException("无法加载类: " + name, e);
}
}
/**
* 检查类文件是否被修改
*/
public boolean isClassModified() {
try {
String path = className.replace('.', '/').concat(".class");
File file = new File(classPath, path);
if (!file.exists()) {
return false;
}
long lastModified = file.lastModified();
Long previousModified = classModifiedTimes.get(className);
if (previousModified == null || previousModified != lastModified) {
classModifiedTimes.put(className, lastModified);
return true;
}
return false;
} catch (Exception e) {
return false;
}
}
}
热部署演示程序
import java.io.*;
import java.lang.reflect.Method;
/**
* 热部署演示
*/
public class HotDeployDemo {
private static final String CLASS_PATH = "./temp";
private static final String CLASS_NAME = "com.example.DynamicService";
public static void main(String[] args) throws Exception {
// 创建模拟的动态服务类源码
createTestClass();
compileTestClass();
// 加载并执行
loadAndExecute();
// 模拟修改代码
Thread.sleep(2000);
modifyTestClass();
compileTestClass();
// 再次加载并执行(热部署)
loadAndExecute();
}
private static void loadAndExecute() {
try {
HotDeployClassLoader loader = new HotDeployClassLoader(CLASS_NAME, CLASS_PATH);
// 检查类是否被修改
if (loader.isClassModified()) {
System.out.println("检测到类文件更新,重新加载...");
}
Class<?> clazz = loader.loadClass(CLASS_NAME);
Object instance = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("getVersion");
String version = (String) method.invoke(instance);
Method method2 = clazz.getMethod("greet", String.class);
String greeting = (String) method2.invoke(instance, "World");
System.out.println("版本: " + version);
System.out.println("问候: " + greeting);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void createTestClass() throws IOException {
File dir = new File("./src");
dir.mkdirs();
String code = """
package com.example;
public class DynamicService {
public String getVersion() {
return "v1.0.0";
}
public String greet(String name) {
return "Hello, " + name + "! (v1)";
}
}
""";
File sourceFile = new File("./src/com/example/DynamicService.java");
sourceFile.getParentFile().mkdirs();
Files.write(sourceFile.toPath(), code.getBytes());
}
private static void modifyTestClass() throws IOException {
String code = """
package com.example;
public class DynamicService {
public String getVersion() {
return "v2.0.0";
}
public String greet(String name) {
return "Hello, " + name + "! (v2 - updated)";
}
}
""";
File sourceFile = new File("./src/com/example/DynamicService.java");
Files.write(sourceFile.toPath(), code.getBytes());
// 复制到 class path
Files.copy(sourceFile.toPath(),
Path.of(CLASS_PATH, "com/example/DynamicService.java"),
StandardCopyOption.REPLACE_EXISTING);
}
}
插件系统架构
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
/**
* 插件管理器 - 演示动态加载插件
*/
public class PluginManager {
private final Map<String, Class<?>> plugins = new ConcurrentHashMap<>();
private final Map<String, ClassLoader> loaders = new ConcurrentHashMap<>();
private final String pluginPath;
public PluginManager(String pluginPath) {
this.pluginPath = pluginPath;
}
/**
* 加载所有插件
*/
public void loadPlugins() {
File dir = new File(pluginPath);
if (!dir.exists() || !dir.isDirectory()) {
System.out.println("插件目录不存在: " + pluginPath);
return;
}
for (File jarFile : dir.listFiles((d, name) -> name.endsWith(".jar"))) {
loadPlugin(jarFile);
}
}
/**
* 加载单个插件
*/
public void loadPlugin(File jarFile) {
try {
// 创建URLClassLoader
URL url = jarFile.toURI().toURL();
URLClassLoader loader = new URLClassLoader(new URL[]{url},
this.getClass().getClassLoader());
// 扫描jar包中的插件类
try (JarFile jar = new JarFile(jarFile)) {
jar.stream()
.filter(e -> e.getName().endsWith(".class"))
.filter(e -> !e.getName().contains("$"))
.forEach(e -> {
try {
String className = e.getName()
.replace('/', '.')
.replace(".class", "");
// 加载并验证是否为插件
Class<?> clazz = loader.loadClass(className);
if (isPlugin(clazz)) {
String pluginName = getPluginName(clazz);
plugins.put(pluginName, clazz);
loaders.put(pluginName, loader);
System.out.println("成功加载插件: " + pluginName);
}
} catch (Exception ex) {
// 忽略无法加载的类
}
});
}
} catch (Exception e) {
System.err.println("加载插件失败: " + jarFile.getName());
e.printStackTrace();
}
}
/**
* 创建插件实例
*/
public <T> T createPlugin(String pluginName, Class<T> pluginType) {
Class<?> clazz = plugins.get(pluginName);
if (clazz == null) {
throw new IllegalArgumentException("插件不存在: " + pluginName);
}
try {
return pluginType.cast(clazz.getDeclaredConstructor().newInstance());
} catch (Exception e) {
throw new RuntimeException("创建插件实例失败", e);
}
}
/**
* 卸载插件
*/
public void unloadPlugin(String pluginName) {
plugins.remove(pluginName);
ClassLoader loader = loaders.remove(pluginName);
if (loader instanceof URLClassLoader) {
try {
((URLClassLoader) loader).close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("卸载插件: " + pluginName);
}
/**
* 判断是否为有效的插件类
*/
private boolean isPlugin(Class<?> clazz) {
return clazz.isAnnotationPresent(Plugin.class) ||
interfacesContainPlugin(clazz);
}
/**
* 检查接口
*/
private boolean interfacesContainPlugin(Class<?> clazz) {
for (Class<?> iface : clazz.getInterfaces()) {
if (iface.getName().contains("Plugin") ||
iface == PluginInterface.class) {
return true;
}
}
return false;
}
/**
* 获取插件名称
*/
private String getPluginName(Class<?> clazz) {
Plugin annotation = clazz.getAnnotation(Plugin.class);
if (annotation != null && !annotation.name().isEmpty()) {
return annotation.name();
}
return clazz.getSimpleName();
}
// 插件注解
public @interface Plugin {
String name() default "";
}
// 插件接口
public interface PluginInterface {
void execute();
}
}
/**
* 插件演示类
*/
@PluginManager.Plugin(name = "demo-plugin")
public class DemoPlugin implements PluginManager.PluginInterface {
@Override
public void execute() {
System.out.println("执行演示插件...");
System.out.println("插件类加载器: " + this.getClass().getClassLoader());
System.out.println("插件父加载器: " + this.getClass().getClassLoader().getParent());
}
}
类加载器隔离案例
import java.lang.reflect.Method;
import java.net.URLClassLoader;
import java.io.File;
/**
* 类加载器隔离演示
*/
public class ClassLoaderIsolationDemo {
public static void main(String[] args) throws Exception {
System.out.println("=== 类加载器隔离演示 ===\n");
// 演示1:相同类名的不同版本
demonstrateSameClassDiffVersions();
// 演示2:父子类加载器可见性
demonstrateParentChildVisibility();
// 演示3:线程上下文类加载器
demonstrateContextClassLoader();
}
private static void demonstrateSameClassDiffVersions() throws Exception {
System.out.println("--- 演示1:同一个类在不同类加载器中的隔离 ---");
File version1Dir = new File("./lib/version1");
File version2Dir = new File("./lib/version2");
// 创建两个独立的类加载器
URLClassLoader loader1 = new URLClassLoader(
new java.net.URL[]{version1Dir.toURI().toURL()});
URLClassLoader loader2 = new URLClassLoader(
new java.net.URL[]{version2Dir.toURI().toURL()});
// 加载同一个类
Class<?> class1 = loader1.loadClass("com.example.VersionedService");
Class<?> class2 = loader2.loadClass("com.example.VersionedService");
System.out.println("类1的加载器: " + class1.getClassLoader());
System.out.println("类2的加载器: " + class2.getClassLoader());
System.out.println("它们是不同的类(实例): " + (class1 != class2));
// 创建实例并调用方法
Object obj1 = class1.getDeclaredConstructor().newInstance();
Object obj2 = class2.getDeclaredConstructor().newInstance();
Method method1 = class1.getMethod("getVersion");
Method method2 = class2.getMethod("getVersion");
System.out.println("版本1: " + method1.invoke(obj1));
System.out.println("版本2: " + method2.invoke(obj2));
// 注意:类型不能互转
System.out.println("对象类型不同: " + (obj1.getClass() != obj2.getClass()));
// 关闭加载器
loader1.close();
loader2.close();
}
private static void demonstrateParentChildVisibility() throws Exception {
System.out.println("\n--- 演示2:父子类加载器的可见性 ---");
// 创建子类加载器
URLClassLoader childLoader = new URLClassLoader(
new java.net.URL[]{new File("./custom").toURI().toURL()},
ClassLoader.getSystemClassLoader()
);
// 子加载器可以看到父加载器的类
try {
Class<?> stringClass = childLoader.loadClass("java.lang.String");
System.out.println("子加载器可以加载String: " + stringClass);
} catch (ClassNotFoundException e) {
System.out.println("无法加载String");
}
// 但是使用双亲委派模型
Class<?> customClass = childLoader.loadClass("com.example.CustomClass");
System.out.println("用户类的加载器: " + customClass.getClassLoader());
// 验证双亲委派
System.out.println("自定义类加载器委派给父加载器: " +
(customClass.getClassLoader() == ClassLoader.getSystemClassLoader()));
childLoader.close();
}
private static void demonstrateContextClassLoader() throws Exception {
System.out.println("\n--- 演示3:线程上下文类加载器 ---");
// 获取当前线程
Thread thread = Thread.currentThread();
System.out.println("当前线程: " + thread.getName());
System.out.println("原始的上下文加载器: " + thread.getContextClassLoader());
// 创建新类加载器并设置为上下文加载器
URLClassLoader customLoader = new URLClassLoader(
new java.net.URL[]{new File("./context").toURI().toURL()},
thread.getContextClassLoader()
);
// 修改线程上下文加载器
thread.setContextClassLoader(customLoader);
System.out.println("修改后的上下文加载器: " + thread.getContextClassLoader());
// 使用上下文加载器加载类
Class<?> clazz = Thread.currentThread()
.getContextClassLoader()
.loadClass("com.example.ContextService");
System.out.println("通过上下文加载器加载的类: " + clazz.getClassLoader());
// 恢复原始的上下文加载器
thread.setContextClassLoader(thread.getContextClassLoader().getParent());
System.out.println("恢复后的上下文加载器: " + thread.getContextClassLoader());
customLoader.close();
}
}
实际应用案例:插件式加密解密框架
import java.util.*;
import java.lang.reflect.*;
import java.util.concurrent.*;
/**
* 可扩展的算法框架 - 通过类加载器动态加载不同的算法实现
*/
public class AlgorithmFramework {
// 算法接口
public interface Algorithm {
String getName();
String encrypt(String data);
String decrypt(String encryptedData);
}
private final Map<String, Algorithm> algorithms = new ConcurrentHashMap<>();
private final Map<String, ClassLoader> algorithmLoaders = new ConcurrentHashMap<>();
private final String algorithmPath;
public AlgorithmFramework(String algorithmPath) {
this.algorithmPath = algorithmPath;
loadDefaultAlgorithms();
}
/**
* 加载默认算法
*/
private void loadDefaultAlgorithms() {
// 内置算法 - AES
registerAlgorithm("AES", new AESAlgorithm());
// 内置算法 - Caesar
registerAlgorithm("Caesar", new CaesarAlgorithm());
}
/**
* 注册算法
*/
public void registerAlgorithm(String name, Algorithm algorithm) {
algorithms.put(name, algorithm);
System.out.println("注册算法: " + name);
}
/**
* 动态加载算法插件
*/
public void loadAlgorithmPlugin(String jarFilePath, String className) {
try {
// 创建独立类加载器
URLClassLoader loader = new URLClassLoader(
new java.net.URL[]{new File(jarFilePath).toURI().toURL()},
this.getClass().getClassLoader()
);
// 加载算法类
Class<?> clazz = loader.loadClass(className);
// 验证是否是算法实现
if (!Algorithm.class.isAssignableFrom(clazz)) {
throw new IllegalArgumentException("类 " + className + " 不是Algorithm的实现");
}
// 创建实例并注册
Algorithm algorithm = (Algorithm) clazz.getDeclaredConstructor().newInstance();
registerAlgorithm(algorithm.getName(), algorithm);
algorithmLoaders.put(algorithm.getName(), loader);
} catch (Exception e) {
throw new RuntimeException("加载算法插件失败: " + className, e);
}
}
/**
* 卸载算法插件
*/
public void unloadAlgorithm(String name) {
Algorithm algorithm = algorithms.remove(name);
if (algorithm != null) {
ClassLoader loader = algorithmLoaders.remove(name);
System.out.println("卸载算法: " + name);
if (loader instanceof URLClassLoader) {
try {
((URLClassLoader) loader).close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 获取算法
*/
public Algorithm getAlgorithm(String name) {
Algorithm algorithm = algorithms.get(name);
if (algorithm == null) {
throw new IllegalArgumentException("未知算法: " + name);
}
return algorithm;
}
/**
* 使用指定算法加密
*/
public String encrypt(String algorithmName, String data) {
Algorithm algorithm = getAlgorithm(algorithmName);
return algorithm.encrypt(data);
}
/**
* 使用指定算法解密
*/
public String decrypt(String algorithmName, String encryptedData) {
Algorithm algorithm = getAlgorithm(algorithmName);
return algorithm.decrypt(encryptedData);
}
/**
* 列出所有可用算法
*/
public Set<String> listAlgorithms() {
return algorithms.keySet();
}
// 内置AES算法实现(简化版)
private static class AESAlgorithm implements Algorithm {
@Override
public String getName() {
return "AES";
}
@Override
public String encrypt(String data) {
// 简化的加密实现(实际应用中应该使用标准AES)
return "AES加密(" + data + ")";
}
@Override
public String decrypt(String encryptedData) {
// 简化的解密实现
return encryptedData.substring(5, encryptedData.length() - 1);
}
}
// 内置Caesar算法实现
private static class CaesarAlgorithm implements Algorithm {
private static final int SHIFT = 3;
@Override
public String getName() {
return "Caesar";
}
@Override
public String encrypt(String data) {
return shift(data, SHIFT);
}
@Override
public String decrypt(String encryptedData) {
return shift(encryptedData, -SHIFT);
}
private String shift(String data, int shift) {
StringBuilder result = new StringBuilder();
for (char c : data.toCharArray()) {
if (Character.isLetter(c)) {
char base = Character.isUpperCase(c) ? 'A' : 'a';
result.append((char) ((c - base + shift + 26) % 26 + base));
} else {
result.append(c);
}
}
return result.toString();
}
}
public static void main(String[] args) throws Exception {
System.out.println("=== 算法框架演示 ===\n");
// 创建框架
AlgorithmFramework framework = new AlgorithmFramework("./algorithms");
// 列出内建算法
System.out.println("内建算法: " + framework.listAlgorithms());
// 使用AES算法
String data = "Hello World";
String aesEncrypted = framework.encrypt("AES", data);
String aesDecrypted = framework.decrypt("AES", aesEncrypted);
System.out.println("\nAES加密: " + aesEncrypted);
System.out.println("AES解密: " + aesDecrypted);
// 使用Caesar算法
String caesarEncrypted = framework.encrypt("Caesar", data);
String caesarDecrypted = framework.decrypt("Caesar", caesarEncrypted);
System.out.println("\nCaesar加密: " + caesarEncrypted);
System.out.println("Caesar解密: " + caesarDecrypted);
// 动态加载第三方算法插件(如果有)
if (new File("./algorithms/my-algorithm.jar").exists()) {
System.out.println("\n正在加载第三方算法...");
framework.loadAlgorithmPlugin("./algorithms/my-algorithm.jar",
"com.custom.CustomAlgorithm");
System.out.println("加载后的算法: " + framework.listAlgorithms());
}
// 实现算法接口的示例插件类
createExamplePlugins();
}
private static void createExamplePlugins() {
// 这里可以创建示例插件类
// 实际项目中可以通过反射动态加载
}
}
核心要点总结
类加载器的双亲委派机制
public class ParentDelegationDemo {
public static void main(String[] args) throws Exception {
// 双亲委派的完整流程
ClassLoader bootstrap = null; // Bootstrap ClassLoader (JVM原生)
ClassLoader platform = ClassLoader.getPlatformClassLoader(); // Platform
ClassLoader system = ClassLoader.getSystemClassLoader(); // System
ClassLoader custom = new CustomClassLoader(""); // 自定义
// 层级关系
System.out.println("自定义的父加载器: " + custom.getParent());
System.out.println("系统加载器的父加载器: " + system.getParent());
// 委派流程演示
System.out.println("\n双亲委派流程:");
System.out.println("1. Custom加载器尝试加载类");
System.out.println("2. 委托给Parent: System");
System.out.println("3. System委托给Parent: Platform");
System.out.println("4. Platform委托给Bootstrap");
System.out.println("5. Bootstrap找到类则返回,否则向下委托");
System.out.println("6. 最终由Custom尝试加载");
// 实际验证
Class<?> clazz = custom.loadClass("java.lang.String");
System.out.println("\n加载String类的实际加载器: " + clazz.getClassLoader());
// 输出null,因为String由Bootstrap加载
}
}
类加载器的最佳实践
public class BestPracticesDemo {
/**
* 正确获取类加载器的模式
*/
public static ClassLoader getBestClassLoader() {
// 1. 线程上下文类加载器(推荐用于框架)
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl != null) {
return cl;
}
// 2. 当前类加载器(推荐用于插件)
cl = BestPracticesDemo.class.getClassLoader();
if (cl != null) {
return cl;
}
// 3. 系统类加载器(最后的选择)
return ClassLoader.getSystemClassLoader();
}
/**
* 资源加载的注意事项
*/
public static void loadResources() {
// 使用getResourceAsStream而不是getResource
try (InputStream is = BestPracticesDemo.class
.getClassLoader()
.getResourceAsStream("config.properties")) {
// 处理资源
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 避免的常见错误
*/
public static void avoidCommonMistakes() {
// 错误1:硬编码类加载器
// ClassLoader cl = ClassLoader.getSystemClassLoader(); // 不推荐
// 错误2:省略null检查
// 应该先获取线程上下文类加载器并检查null
// 错误3:在静态初始化中加载外部类
// 应该在方法中按需加载
// 错误4:不处理ClassNotFoundException
// 总是捕获或声明抛出
}
}
这些案例展示了Java类加载器的核心概念和实际应用,通过学习和实践这些示例,您将能够:
- 理解类加载器的基本概念和层级结构
- 自定义类加载器实现特殊加载逻辑
- 实现热部署功能
- 构建插件化的系统架构
- 理解并正确使用双亲委派模型
- 避免类加载器相关的常见问题
建议在实际项目中根据需求选择适当的类加载器模式,并注意内存管理和类加载器的正确使用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播