Задача: Загрузчик классов
Исходник: Запуск jar-приложения из любого источника, язык: java [code #194, hits: 8731]
автор: - [добавлен: 02.05.2007]
  1. /* From http://java.sun.com/docs/books/tutorial/index.html */
  2.  
  3.  
  4. import java.io.IOException;
  5. import java.lang.reflect.InvocationTargetException;
  6. import java.lang.reflect.Method;
  7. import java.lang.reflect.Modifier;
  8. import java.net.JarURLConnection;
  9. import java.net.MalformedURLException;
  10. import java.net.URL;
  11. import java.net.URLClassLoader;
  12. import java.util.jar.Attributes;
  13.  
  14. /**
  15. * Runs a jar application from any url. Usage is 'java JarRunner url [args..]'
  16. * where url is the url of the jar file and args is optional arguments to be
  17. * passed to the application's main method.
  18. */
  19. public class JarRunner {
  20. public static void main(String[] args) {
  21. if (args.length < 1) {
  22. usage();
  23. }
  24. URL url = null;
  25. try {
  26. url = new URL(args[0]);
  27. } catch (MalformedURLException e) {
  28. fatal("Invalid URL: " + args[0]);
  29. }
  30. // Create the class loader for the application jar file
  31. JarClassLoader cl = new JarClassLoader(url);
  32. // Get the application's main class name
  33. String name = null;
  34. try {
  35. name = cl.getMainClassName();
  36. } catch (IOException e) {
  37. System.err.println("I/O error while loading JAR file:");
  38. e.printStackTrace();
  39. System.exit(1);
  40. }
  41. if (name == null) {
  42. fatal("Specified jar file does not contain a 'Main-Class'"
  43. + " manifest attribute");
  44. }
  45. // Get arguments for the application
  46. String[] newArgs = new String[args.length - 1];
  47. System.arraycopy(args, 1, newArgs, 0, newArgs.length);
  48. // Invoke application's main class
  49. try {
  50. cl.invokeClass(name, newArgs);
  51. } catch (ClassNotFoundException e) {
  52. fatal("Class not found: " + name);
  53. } catch (NoSuchMethodException e) {
  54. fatal("Class does not define a 'main' method: " + name);
  55. e.getTargetException().printStackTrace();
  56. System.exit(1);
  57. }
  58. }
  59.  
  60. private static void fatal(String s) {
  61. System.err.println(s);
  62. System.exit(1);
  63. }
  64.  
  65. private static void usage() {
  66. fatal("Usage: java JarRunner url [args..]");
  67. }
  68. }
  69.  
  70. /**
  71. * A class loader for loading jar files, both local and remote.
  72. */
  73.  
  74. class JarClassLoader extends URLClassLoader {
  75. private URL url;
  76.  
  77. /**
  78. * Creates a new JarClassLoader for the specified url.
  79. *
  80. * @param url
  81. * the url of the jar file
  82. */
  83. public JarClassLoader(URL url) {
  84. super(new URL[] { url });
  85. this.url = url;
  86. }
  87.  
  88. /**
  89. * Returns the name of the jar file main class, or null if no "Main-Class"
  90. * manifest attributes was defined.
  91. */
  92. public String getMainClassName() throws IOException {
  93. URL u = new URL("jar", "", url + "!/");
  94. JarURLConnection uc = (JarURLConnection) u.openConnection();
  95. Attributes attr = uc.getMainAttributes();
  96. return attr != null ? attr.getValue(Attributes.Name.MAIN_CLASS) : null;
  97. }
  98.  
  99. /**
  100. * Invokes the application in this jar file given the name of the main class
  101. * and an array of arguments. The class must define a static method "main"
  102. * which takes an array of String arguemtns and is of return type "void".
  103. *
  104. * @param name
  105. * the name of the main class
  106. * @param args
  107. * the arguments for the application
  108. * @exception ClassNotFoundException
  109. * if the specified class could not be found
  110. * @exception NoSuchMethodException
  111. * if the specified class does not contain a "main" method
  112. * @exception InvocationTargetException
  113. * if the application raised an exception
  114. */
  115. public void invokeClass(String name, String[] args)
  116. Class c = loadClass(name);
  117. Method m = c.getMethod("main", new Class[] { args.getClass() });
  118. m.setAccessible(true);
  119. int mods = m.getModifiers();
  120. if (m.getReturnType() != void.class || !Modifier.isStatic(mods)
  121. || !Modifier.isPublic(mods)) {
  122. throw new NoSuchMethodException("main");
  123. }
  124. try {
  125. m.invoke(null, new Object[] { args });
  126. } catch (IllegalAccessException e) {
  127. // This should not happen, as we have disabled access checks
  128. }
  129. }
  130.  
  131. }
Из командной строки задается jar url файла, т.е. адрес этого jar файла, который может представлять из себя как адрес в сети на http/ftp серверах, так и локальный путь в текущей файловой системе.
Далее jar средствами виртуальной машины загружается, определяется Main файл и запускается с остальными аргументами, идущими из командной строки.
Тестировалось на: java 1.5.0_04

+добавить реализацию