Содержит ли тип параметра метода информацию о его загрузчике классов?

#java

Вопрос:

Два класса с одинаковым именем, но загруженные разными загрузчиками классов, будут считаться разными. Тогда метод использует такой тип параметра, может ли этот метод использовать только экземпляр, загруженный загрузчиком классов A, но экземпляр, загруженный загрузчиком классов B, не может?

Следующая моя простая попытка

 // src/main/java/com/example/Main.java
// src/main/java/com/example/classloader/Foo.java

public class Main {
  public static void main(final String[] args)
      throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException,
          NoSuchMethodException, InvocationTargetException {
    final String path = Main.class.getClassLoader().getResource("").getPath();
    final CustomerClassLoader customerClassLoader = new CustomerClassLoader(path);

    final Class<?> customFooClass = customerClassLoader.loadClass("com.example.classloader.Foo");
    final Object foo1 = customFooClass.newInstance();

    try (final ByteArrayOutputStream memory = new ByteArrayOutputStream()) {
      try (final ObjectOutputStream de = new ObjectOutputStream(memory)) {
        de.writeObject(foo1);
      }
      try (final ByteArrayInputStream in = new ByteArrayInputStream(memory.toByteArray())) {
        try (final ObjectInputStream se = new ObjectInputStream(in)) {
          final Foo foo2 = ((Foo) se.readObject());
          Main.class.getMethod("from", Foo.class).invoke(new Main(), foo2);

          final Class<?> customMainClass = customerClassLoader.loadClass("com.example.Main");
          customMainClass
              .getMethod("from", customFooClass)
              .invoke(customMainClass.newInstance(), foo1);
        }
      }
    }
  }

  public void from(final Foo foo) {
    System.out.println(foo.getClass().getClassLoader());
  }
}


/**
package com.example.classloader;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;

public class CustomerClassLoader extends ClassLoader {

  private final String rootDirPath;

  public CustomerClassLoader(String rootDirPath) {
    this.rootDirPath = rootDirPath;
  }

  @Override
  public Class<?> loadClass(String name) throws ClassNotFoundException {
    if (name.toLowerCase().contains("foo")) {
      return this.findClass(name);
    }
    return super.loadClass(name);
  }

  @Override
  protected Class<?> findClass(String name) throws ClassNotFoundException {
    File javaFile = new File(rootDirPath   name.replace('.', File.separatorChar)   ".class");
    if (javaFile != null amp;amp; javaFile.exists()) {
      System.out.println(javaFile);
      try {
        byte[] javaClassBytes = FileUtils.readFileToByteArray(javaFile);
        return defineClass(name, javaClassBytes, 0, javaClassBytes.length);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    throw new ClassNotFoundException(javaFile.getPath());
  }
}
**/
 

на экране появится ошибка .getMethod("from", customFooClass)

 Exception in thread "main" java.lang.NoSuchMethodException: com.example.Main.from(com.example.classloader.Foo)
 

Что я должен сделать Main#from(Foo) , чтобы получить экземпляр Foo, созданный CustomerClassLoader ?

Большое спасибо.


Спасибо @user207421, после исправления nameToLowerCase.contains("foo") в nameToLowerCase.contains("foo") || nameToLowerCase.contains("main") ,

           customMainClass
              .getMethod("from", customFooClass)
              .invoke(customMainClass.newInstance(), foo1);
 

работает хорошо.

Поэтому я предполагаю, что загрузчик классов типа параметра должен совпадать с загрузчиком классов его класса.

Комментарии:

1. Было бы хорошо иметь больше контекста, поскольку это, по-видимому, проблема дизайна. Вам следует избегать загрузки того же типа в другой загрузчик классов.

2. Вместо Foo.class буквального цитирования загрузите класс из своего загрузчика классов.

3. @user207421 customFooClass загружается моим загрузчиком классов в getMethod("from", customFooClass)

4. Но у вас есть Foo.class место, где вы получаете метод Main.class.getMethod("from", Foo.class) .

5. Вы можете найти документацию ObjectInputStream.resolveClass информативной.