Является ли null экземпляром чего-либо?
blockquote>Нет. Вот почему
null instanceof X
вернетfalse
для всех классовX
. (Не обманывайтесь тем фактом, что вы можете назначитьnull
переменной, тип которой является типом объекта. Строго говоря, назначение подразумевает неявное преобразование типа, см. Ниже.)Что устанавливает 'null' к?
blockquote>Это единственный и единственный член нулевого типа, где нулевой тип определяется следующим образом:
«Существует также специальный тип null, тип выражения null, который не имеет имени. Поскольку тип null не имеет имени, невозможно объявить переменную нулевого типа или применить к нулевому типу. Нулевая ссылка - это единственное возможное значение выражения типа null. Нулевая ссылка всегда может быть передана любому ссылочному типу. На практике программист может игнорировать нулевой тип и просто притворяться, что null - это просто специальный литерал, который может быть любого ссылочного типа. " JLS 4.1
Что такое null?
blockquote>См. выше. В некоторых контекстах
null
используется для обозначения «no object» или «unknown» или «unavailable», но эти значения являются специфичными для приложения.Как это отображается в памяти?
blockquote>Это специфично для реализации, и вы не сможете увидеть представление
null
в чистой программе Java. (Ноnull
представляется как нулевой машинный адрес / указатель в большинстве, если не во всех реализациях Java.)
.file "test .c "
Команды, начинающиеся с. директивы ассемблеру. Здесь просто говорится, что это "file.c", эта информация может быть экспортирована в отладочную информацию exe.
.def ___main; .scl 2; .type 32; .endef
Директивы .def определяют символ отладки. scl 2 означает класс хранилища 2 (класс внешнего хранилища). Тип 32 означает, что этот sumbol является функцией. Эти числа будут определены в формате pe-coff exe-format
___ main - это функция, вызываемая, которая заботится о начальной загрузке, необходимой gcc (она будет делать такие вещи, как запуск статических инициализаторов c ++ и другие необходимые вспомогательные операции).
. текст
Начинает текстовый раздел - здесь находится код.
.globl _main
определяет символ _main как глобальный, что делает его видимым для компоновщика и других модулей, связанных с.
.def _main ; .scl 2; .type 32; .endef
То же, что и _main, создает символы отладки, указывающие, что _main - это функция. Это может использоваться отладчиками.
_main:
Запускает новую метку (в конце концов, это адрес). указанная выше директива .globl делает этот адрес видимым для других объектов.
pushl% ebp
Сохраняет старый указатель кадра (регистр ebp) в стеке (чтобы его можно было вернуть на место после завершения этой функции)
movl% esp,% ebp
Перемещает указатель стека в регистр EBP. ebp часто называют указателем кадра, он указывает на верхнюю часть значений стека в текущем «кадре» (обычно функция) (обращение к переменным в стеке через ebp может помочь отладчикам)
и l $ -16,% esp
И добавляет в стек значение fffffff0, которое эффективно выравнивает его по границе 16 байт. Доступ к выровненным значениям в стеке намного быстрее, чем если бы они не были выровнены. Все эти предыдущие инструкции в значительной степени являются прологом стандартной функции.
call ___main
Вызывает функцию ___main, которая будет выполнять инициализацию того, что нужно gcc. Вызов поместит указатель текущей инструкции в стек и перейдет к адресу ___ main
movl $ 0,% eax
переместите 0 в регистр eax (0 в return 0;) регистр eax используется для хранения значений, возвращаемых функцией для соглашения о вызовах stdcall.
leave
Инструкция leave в значительной степени является сокращением для
movl ebp, esp попл эбп
т.е. он «отменяет» все, что было сделано в начале функции - восстанавливает указатель кадра и стек в его прежнее состояние.
ret
Возвращает тому, кто вызвал эту функцию. Он вытолкнет указатель инструкции из стека (который будет помещен туда соответствующей инструкцией вызова) и перейдет туда.
Что касается и l $ -16,% esp
Таким образом, он замаскирует последние 4 бита ESP (между прочим: 2 ** 4 равно 16) и сохранит все остальные биты (независимо от того, является ли целевая система 32 или 64 бит).
__ main
- это подпрограмма в стандартной библиотеке GNU, которая заботится о различных инициализациях при запуске. Это не является строго необходимым для программ на языке C, но требуется на тот случай, если код C связан с C ++.
_main
- ваша основная подпрограмма. Поскольку и _main
, и __ main
являются местоположениями кода, они имеют одинаковый класс и тип хранилища. Я еще не нашел определения для .scl
и .type
. Вы можете получить некоторое освещение, определив несколько глобальных переменных.
Первые три инструкции устанавливают кадр стека, который является техническим термином для рабочего хранилища подпрограммы - по большей части локальных и временных переменных. Нажатие ebp
сохраняет базу кадра стека вызывающего абонента. Ввод esp
в ebp
устанавливает основу нашего кадра стека. и
выравнивают кадр стека по 16-байтовой границе на тот случай, если какие-либо локальные переменные в стеке требуют 16-байтового выравнивания (для инструкций x86 SIMD требуется такое выравнивание, но выравнивание действительно ускоряет обычные типы, такие как int
s и float
s.
На этом этапе обычно ожидается, что esp
будет перемещен вниз в памяти, чтобы выделить пространство стека для локальных переменных. main
не имеет ничего, поэтому gcc не беспокоит.
Вызов __ main
является специальным для основной точки входа и обычно не появляется в подпрограммах.
Остальное идет, как вы и догадались .. Регистр eax
- это место, куда можно поместить целочисленные коды возврата в двоичной спецификации. leave
отменяет кадр стека, а ret
возвращается к вызывающему. В этом случае вызывающей стороной является среда выполнения C нижнего уровня, которая будет выполнять дополнительную магию (например, вызывать функции atexit ()
, устанавливать код выхода для процесса и запрашивать у операционной системы завершение процесса.
В дополнение к и l $ -16,% esp
, это работает, потому что установка младших битов на ноль всегда приводит к понижению % esp
] по значению, а стек растет вниз на x86.
У меня нет ответов на все, но я могу объяснить то, что знаю.
ebp
используется функцией для сохранения начального состояния esp
во время выполнения - ссылка на то, где аргументы передаются функции, а где - ее собственные локальные переменные. Первое, что делает функция, это сохраняет статус заданного ebp
при выполнении pushl% ebp
, это жизненно важно для функции, которая выполняет вызов, а затем заменяет его своим собственным текущая позиция в стеке esp
выполнение movl% esp,% ebp
. Обнуление последних 4 бит ebp
на этом этапе зависит от GCC, я не знаю, почему этот компилятор это делает. Это сработало бы и без этого. Теперь, наконец, мы переходим к делу, звоним ___ main
, кто __main? Я тоже не знаю ... возможно, больше процедур, специфичных для GCC, и, наконец, единственное, что делает ваш main (), устанавливает возвращаемое значение как 0 с помощью movl $ 0,% eax
и leave
, что аналогично выполнению movl% ebp,% esp; popl% ebp
для восстановления состояния ebp
, затем ret
для завершения. ret
pops eip
и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .
По большей части это управление стеком. Некоторое время назад я написал подробное руководство о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...
установите возвращаемое значение как 0 с помощью movl $ 0,% eax
и leave
, что аналогично выполнению movl% ebp,% esp; popl% ebp
для восстановления состояния ebp
, затем ret
для завершения. ret
pops eip
и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .
По большей части это управление стеком. Некоторое время назад я написал подробный учебник о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...
установите возвращаемое значение как 0 с помощью movl $ 0,% eax
и leave
, что аналогично выполнению movl% ebp,% esp; popl% ebp
для восстановления состояния ebp
, затем ret
для завершения. ret
pops eip
и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .
По большей части это управление стеком. Некоторое время назад я написал подробное руководство о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...
ret
pops eip
и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .
По большей части это управление стеком. Некоторое время назад я написал подробное руководство о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...
ret
pops eip
и продолжает поток потока с этой точки, где бы он ни находился (поскольку это main (), этот ret, вероятно, приводит к некоторой процедуре ядра, которая обрабатывает конец программы) .
По большей части это управление стеком. Некоторое время назад я написал подробный учебник о том, как используется стек, было бы полезно объяснить, почему все эти вещи сделаны. Но это на португальском ...
Если я правильно помню, « * chrome
» используется для запуска специального режима Firefox (режима, в котором ваше приложение имеет больше привилегии - с меньшими ограничениями безопасности) ; так что запускается именно Firefox, а не Google Chrome.
Если вы хотите запустить Google Chrome, вам нужно будет использовать что-то еще, кроме « * chrome
».
Использование Selenium RC в интерактивном режиме, примерно так:
$ java -jar selenium-server.jar -interactive
и неправильное использование команды getNewBrowserSession
:
cmd=getNewBrowserSession
Я получил список поддерживаемых браузеров:
23:43:09.317 INFO - Got result: Failed to start new browser session: Browser not supported:
(Did you forget to add a *?)
Supported browsers include:
*firefox
*mock
*firefoxproxy
*pifirefox
*chrome
*iexploreproxy
*iexplore
*firefox3
*safariproxy
*googlechrome
*konqueror
*firefox2
*safari
*piiexplore
*firefoxchrome
*opera
*iehta
*custom
on session null
Итак, я предполагаю , что вы сможете запускать Google Chrome, используя " * googlechrome
" вместо " * chrome
".
Я не использую Windows, поэтому я не могу попробовать самостоятельно ... И я не могу найти в документации ничего, что могло бы поддержать меня ... Тем не менее, с немного удачи, это может вам помочь ...
В любом случае, получайте удовольствие!
Кстати: не Google Chrome изобрел термин «хром»; это означает много всего ,