2013-05-09 2 views
3

Я читаю этот учебник от Oracle http://docs.oracle.com/javase/tutorial/extra/generics/legacy.htmlОбобщения в Java - Взаимодействие с унаследованным кодом

Но я не могу понять, что означает эта линия

Как результат, по технике безопасности типа и целостности виртуальной машины Java никогда не подвергаются риску даже при наличии непроверенных предупреждений.

Может кто-нибудь объяснить это для меня более четко? Добавлено: Что такое «целостность» от JVM и что такое «под угрозой» «действительно означает?

ответ

5

Это означает, что JVM никогда не обманывается, думая, что объект является типом, которого нет. Обманывать время выполнения, думая, что часть данных имеет другой тип, представляет собой мощный вектор атаки, особенно если вы можете обмануть время выполнения, позволяя присвоить значение тому, что, по его мнению, long или int, но на самом деле является указателем.

Основополагающая модель безопасности JVM опирается на объект, являющийся типом, который считает время выполнения .

Я прочитал увлекательную бумагу, в которой подробно описывается атака на машину, на которой работает Java, в которой используется лампа высокой температуры, чтобы резко увеличить ошибки памяти. Затем они использовали программу с миллиардами объектов, стратегически выровненную в памяти, и ждали, что у нее будет спорадический бит. Это привело к тому, что JVM подумал, что имеет дело с другим типом объекта и в конечном итоге разрешает JVM запускать произвольный код (для полного чтения см. Using Memory Errors to Attack a Virtual Machine).

Тот факт, что они использовали бит флип, не имеет отношения к Generics. Но способность обманывать среду исполнения в мышлении объекта другого типа подробно описана в этой статье. Подводя итог, представьте, что вы есть классы A и B:

class A { 
    public long data = 0; 
} 

class B { 
} 

Если вы можете как-то обмануть JVM, чтобы позволить этому:

A aButActuallyB = someMagicAssignment(new B()); 

Где someMagicAssignment это метод, который может взять ссылку на B и как-то вернуть объект референта как A. Затем подумайте о том, что будет на самом деле произойдет, когда вы тогда сделали:

aButActuallyB.data = 0x05124202; 

Вы можете писать в произвольные данные в сыром памяти JVM в! Эти данные могут быть, например, местоположением метода. Изменение его, чтобы указать на содержимое некоторого байтового массива, может позволить вам запустить произвольный код.

Так что, когда Oracle говорит

безопасность типа и целостность виртуальной машины Java никогда не рискует, даже при наличии непроверенных предупреждений.

Что это говорит, что несмотря на то, что вы можете сделать это:

public static <T> T someMagicAssignment(B b){ 
    return (T) b; //unchecked cast warning 
} 

И затем вызвать его:

A a = MyClass.<A>someMagicAssignment(new B()); 

Это все еще собирается сделать проверку выполнения на присвоение - a.

Таким образом, запись этого метода someMagicAssignment не проще, чем раньше. Дженерики никоим образом не увеличили площадь поверхности этого вектора атаки, поскольку JVM игнорирует дженерики в своей системе внутреннего типа. Никогда JVM не позволит вам дать метод List<String>, а затем выполнить этот метод String операций над элементами этого списка, не проверяя при этом, что эти элементы фактически являются String. Никогда не разрешите вам обрабатывать B как A без проверки вручную.

1

Это просто означает, что в вашем коде List<String> stringList или List stringList в вашем коде, после компиляции и запуска, JVM вообще не подвергается риску. JVM видит только List stringList.

Это из-за типа erasure, где параметрический тип Generics стирается (удаляется) во время выполнения.

В этой же статье четко сказано:

В основном, стиранием избавляется от (или удаляет) все общий тип информации. Вся информация о типе между угловыми скобками составляет , поэтому, например, параметризованный тип, такой как List<String> , преобразуется в List.


риск в документации просто означает, что, если у вас есть пример

List<String> stringList = new Arrays.asList("one", "two", "three"); 
String number = stringList.get(0); 

Виртуальная машина Java понимает как:

List stringList = new Arrays.asList("one", "two", "three"); 
String number = (String)stringList.get(0); 

Хотя, второй версия будет жаловаться на Generics raw-types, СП M удаляет параметризованный тип и неявно извлекает элементы как Object, и правила преобразования типов JVM по-прежнему применяются.

JVM never хранит/использует информацию Generics (даже если метаданные находятся в файле класса).

Надеюсь, это поможет.

+0

так что значит «под угрозой»? можете ли вы привести пример того, когда JVM «находится под угрозой»? –

+0

Смотрите мое обновленное сообщение. –

+0

Я понимаю ваше объяснение стирания стилей, но, если я пишу Список stringList = Arrays.asList («один», «два», «три»); Целое число = (целое число) stringList.get (0); не является ли JVM под угрозой? –

1

Я думаю, что то, что они получают, заключается в том, что генерические средства реализованы в компиляторе, но не на виртуальной машине, и поэтому байт-код, который испускает компилятор, одинаковый независимо от того, подавляете ли вы запрещенные предупреждения или нет; подавление непроверенных предупреждений не выполняется таким образом, что обходит проверку типов на уровне виртуальной машины только на уровне компилятора.

0

Ответ в предложении, непосредственно предшествующее, что один:

Причина этого заключается в том, что дженерик реализуются Java компилятора как фронтальное преобразование называется стиранием. Вы можете (почти) подумать об этом как о переводе источника в источник, в результате чего общая версия лазейки() преобразуется в неосновную версию.

Это означает, что из-за стирания исходный код с генериками будет скомпилирован с тем же (или, по крайней мере, похожим) байт-кодом в качестве неосновного исходного кода.