В этом примере только показано, что наследник загрузчика классов должен определить и реализовать методы findClass() и loadClassData() для загрузки описания класса. Когда описание получено, массив байт передается в метод defineClass() для создания экземпляра Class. Для простоты в примере приведен только шаблонный код, без реализации получения байт из сетевого соединения.
Для получения экземпляров классов, загруженных с помощью этого загрузчика, можно воспользоваться методом loadClass():
try { ClassLoader loader = new NetworkClassLoader(host, port); Object main = loader.loadClass( 'Main').newInstance(); } catch(ClassNotFoundException e) { e.printStackTrace(); } catch(InstantiationException e) { e.printStackTrace(); } catch(IllegalAccessException e) { e.printStackTrace(); }
Если такой класс не будет найден, будет брошено исключение ClassNotFoundException, если класс будет найден, но произойдет какая-либо ошибка при создании объекта этого класса – будет брошено исключение InstantiationException, и, наконец, если у вызывающего потока не имеется соответствующих прав для создания экземпляров этого класса (что проверяется менеджером безопасности), будет брошено исключение IllegalAccessException.
SecurityManager – менеджер безопасности
С помощью методов этого класса приложения перед выполнением потенциально опасных операций проверяют, является ли операция допустимой в данном контексте.
Класс SecurityManager содержит много методов с именами, начинающимися с приставки check ('проверить'). Эти методы вызываются из стандартных классов библиотек Java перед тем, как в них будут выполнены потенциально опасные операции. Типичный вызов выглядит примерно следующим образом:
SecurityManager security = System.getSecurityManager(); if(security != null){ security.checkX(…); }
где X – название потенциально опасной операции: Access, Read, Write, Connect, Delete, Exec, Listen и т.д.
Предотвращение вызова производится путем бросания исключения – SecurityException, если вызов операции не разрешен (кроме метода checkTopLevelWindow, который возвращает boolean значение).
Для установки менеджера безопасности в качестве текущего вызывается метод setSecurityManager() в классе System. Соответственно, для его получения нужно вызвать метод getSecurityManager().
В большинстве случаев, если приложение запускается локально, будут разрешены все действия, поскольку в системе SecurityManager отсутствует. Предполагается, что запускаемому локально приложению можно полностью доверять. Если же приложение может быть опасно (например, его код был загружен из сети, как это происходит в случае апплетов), то менеджер безопасности выставляется и его уже нельзя убрать или заменить (попытки вызовут SecurityException ). Он контролирует работу с локальной файловой системой, сетевыми соединениями, потоками исполнения и т.д.
System
Класс System содержит набор полезных статических методов и полей. Экземпляр этого класса не может быть создан или получен.
Пожалуй, наиболее широко используемой возможностью, предоставляемой System, является стандартный вывод, доступный через переменную System.out. Ее тип – PrintStream (потоки данных будут подробно рассматриваться в лекции 15). Стандартный вывод можно перенаправить в другой поток (файл, массив байт и т.д., главное, чтобы это был объект PrintStream ):
public static void main(String[] args) { System.out.println('Study Java'); try { PrintStream print = new PrintStream(new FileOutputStream('d:\file2.txt')); System.setOut(print); System.out.println('Study well'); } catch(FileNotFoundException e) { e.printStackTrace(); } }
При запуске этого кода на экран будет выведено только
Study Java
И в файл 'd:file2.txt' будет записано
Study well
Аналогично могут быть перенаправлены стандартный ввод System.in – вызовом System.setIn (InputStream) и поток вывода сообщений об ошибках System.err – вызовом System.setErr(PrintStream) (по умолчанию все потоки – in, out, err – работают с консолью приложения).
Следующие методы класса System позволяют работать с некоторыми параметрами системы:
public static void runFinalizersOnExit(boolean value) – определяет, будет ли производиться вызов метода finalize() у всех объектов (у кого еще не вызывался), когда выполнение программы будет окончено (по умолчанию выставлено значение false );
public static native long currentTimeMillis() – возвращает текущее время; это время представляется как количество миллисекунд, прошедших с 1 января 1970 года;