Search code examples
javaclassloaderprotected

IllegalAccessException when trying to read protected property from class with different ClassLoader


I have a following files:

src/
 |- cltest/
 |   |- Main.class
 |   |- Test.class
 |   `- TestingClassLoader.class
 `- data (a class cltest.LoadedClass without an extension)

Main.java:

package cltest;

public class Main {
  protected static String field = "TestTestTest";
  public static void main(String[] args) throws Exception {
    Class.forName("cltest.Test");
    Class.forName("cltest.LoadedClass", true, new TestingClassLoader());
  }
}

Test.java and /data

package cltest;

public class Test /* or LoadedClass for /data file */ {
  static {
    System.out.println(Main.field);
  }
}

TestingClassLoader.java

package cltest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.CodeSource;
import java.security.ProtectionDomain;

public class TestingClassLoader extends ClassLoader {
  public Class<?> findClass(String name) throws ClassNotFoundException {
    try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      InputStream is = this.getClass().getResourceAsStream("/data");
      byte[] buf = new byte[256]; int r;
      while ((r = is.read(buf)) != -1) baos.write(buf, 0, r);
      byte[] data = baos.toByteArray();

      return defineClass(null, data, 0, data.length);
    } catch (Exception e) {
      throw new ClassNotFoundException(name, e);
    }
  }
}

This code gives me an error on line Class.forName("cltest.LoadedClass", true, new TestingClassLoader());:

TestTestTest //  (output of 1st Class.forName() call)
Exception in thread "main" java.lang.IllegalAccessError: tried to access field cltest.Main.field from class cltest.LoadedClass
  at cltest.LoadedClass.<clinit>(LoadedClass.java:5)
  at java.lang.Class.forName0(Native Method)
  at java.lang.Class.forName(Unknown Source)
  at cltest.Main.main(Main.java:7)

How I can fix it?


Solution

  • The only way for this to work is for LoadedClass and Main to be in the same classloader (classes are only truly in the same package if they have the same package name and classloader).

    you talk about a "plugin" which needs to access protected methods of main. this is a poor design for a plugin system. if you control these classes, then make the necessary methods public instead of protected.