JDK косяк?

kill-still

java.lang.IllegalAccessError: tried to access class ru.example.AbstractClass from class ru.example.Test

package ru.example;

abstract class AbstractClass {

public String getString {
return "someString";
}

}


package ru.example;

public class NotAbstractClass extends AbstractClass {
}


package ru.anotherpackage;

import ru.example.NotAbstractClass;
import java.util.Optional;

public class Test {

public static void main(String[] args) {
Optional<NotAbstractClass> obj = Optional.ofNullable(new NotAbstractClass;
String string = obj.map(NotAbstractClass::getString).orElse("noString");
System.out.println(string);
}

}

Проверял на 1.8.0.25 и 1.8.0.45 win х64

Hastya

    public State getState {
статический должон быть, не?

kill-still

С чего бы? Если AbstractClass сделать не абстрактым, то всё работает.

evgen5555

Какой тип у container?

kill-still

HashMap, но какое это имеет значение?

evgen5555

А хз, что может происходить. Ты ж не указал, в какой строчке эррор возникает.

kill-still

при вызове: obj.map(NotAbstractClass::getState)

kill-still

прошу прошения: Test должен быть в другом пакете, для того, чтобы воспроизвелось.

kill-still

Connected to the target VM, address: '127.0.0.1:52741', transport: 'socket'
Exception in thread "main" java.lang.IllegalAccessError: tried to access class ru.example.AbstractClass from class ru.anotherpackage.Test
at ru.anotherpackage.Test.lambda$main$0(Test.java:10)
at ru.anotherpackage.Test$$Lambda$1/1989972246.apply(Unknown Source)
at java.util.Optional.map(Optional.java:215)
at ru.anotherpackage.Test.main(Test.java:10)
Disconnected from the target VM, address: '127.0.0.1:52741', transport: 'socket'

Process finished with exit code 1

Hastya

Exception in thread "main" java.lang.IllegalAccessError: tried to access class ru.example.AbstractClass from class ru.anotherpackage.Test
ну, типа, должен быть public abstract?

kill-still

Кому должен? Из всех вариантов не работает только последний:

System.out.println(obj.get.getString;
System.out.println(obj.map(j -> j.getString.orElse("noString";
System.out.println(obj.map(NotAbstractClass::getString).orElse("noString";

Имхо, это косяк. Оно ведь компилится без ошибок, значит считает что всё ок, просто где-то лишняя проверка выполняется.

evgen5555

Пример в начале поста у меня работает без косяков на 1.8.0-25 - с classloader'ами никаких ухищрений не производилось?
http://stackoverflow.com/questions/14070215/java-lang-illegalaccesserror-tried-to-access-field-concreteentity-instance-from

kill-still

Хм, а ты точно Test в другой пакет переложил?

Toma90

Наверное, это баг в javac, этот или какой-то другой.
Моя версия компилятора генерит такой байт-код для обработчика лямды 'NotAbstractClass::getString':
private static java.lang.Object lambda$MR$main$getString$d528cc2d$1(java.lang.Object);
descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
flags: ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: checkcast class ru/example/AbstractClass
4: invokevirtual Method ru/example/AbstractClass.getStringLjava/lang/String;
7: areturn

(Бага в том, что этот код использует недоступный AbstractClass вместо NotAbstractClass.)

kill-still

О, точно, оно. Спасибо.
интересно, b47 это значит 1.8.0.47 ?

Toma90

Да, 1.8.0.47.

kill-still

А вот и нет - вышел u51. Баг в нём не закрыт:
http://www.oracle.com/technetwork/java/javase/8u51-relnotes-...
UPD:
b47 это похоже к 9ой версии относится.
Я правильно понял, что в 8ой версии они его править не собираются?

Toma90

Да, действительно, тот тикет относится только к Java 9. Можно поискать подобный тикет к 8-ой, но это бессмысленно.
Опыт показывает, что в Java полно багов, и проще использовать какой-нибудь workaround, чем ждать фикса.
Оставить комментарий
Имя или ник:
Комментарий: