Changeset 7192
- Timestamp:
- Aug 29, 2016, 2:47:49 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/build.xml
r7190 r7192 709 709 <metainf file="${test.src}/net/sf/basedb/test/extension/jar3/extensions.xml" /> 710 710 <manifest> 711 <attribute name=" X-Extension-Class-Path" value="extension-in-jar1 extension-in-jar2" />711 <attribute name="Class-Path" value="ExtensionOne.jar ExtensionTwo.jar" /> 712 712 </manifest> 713 713 </jar> -
trunk/src/core/net/sf/basedb/util/JarClassLoader.java
r6898 r7192 28 28 import java.util.Map; 29 29 import java.util.HashMap; 30 import java.util.Iterator; 30 31 import java.util.Enumeration; 31 32 import java.util.Vector; … … 135 136 } 136 137 137 138 138 /** 139 139 Get a new class loader for the specified jar file. … … 199 199 */ 200 200 private final Map<File, JarInfo> jarFiles; 201 202 /** 203 Class loaders for extensions. 204 */ 205 private final List<JarClassLoaderProxy> proxyLoaders; 201 206 202 207 /** … … 232 237 classPath = new HashMap<String, List<File>>(); 233 238 jarFiles = new HashMap<File, JarInfo>(); 239 proxyLoaders = new ArrayList<JarClassLoaderProxy>(); 234 240 loadJarFile(mainJarFile, true); 235 241 } … … 338 344 339 345 // 2. Check the system class loader 340 if (c == null && parent != system) c = loadClassInternal(system, name); 341 if (log.isDebugEnabled()) log.debug("system class (" + name + "): " + c); 346 if (c == null && parent != system) 347 { 348 c = loadClassInternal(system, name); 349 if (log.isDebugEnabled()) log.debug("system class (" + name + "): " + c); 350 } 342 351 343 352 // 3. Delegate to parent class loader 344 if (c == null && delegateFirst) c = loadClassInternal(parent, name); 345 if (log.isDebugEnabled()) log.debug("parent class (" + name + "): " + c); 353 if (c == null && delegateFirst) 354 { 355 c = loadClassInternal(parent, name); 356 if (log.isDebugEnabled()) log.debug("parent class (" + name + "): " + c); 357 } 346 358 347 359 // 4. Look for the class in this class path … … 354 366 catch (ClassNotFoundException ex) 355 367 {} 356 }357 if (log.isDebugEnabled()) log.debug("my class (" + name + "): " + c);368 if (log.isDebugEnabled()) log.debug("my class (" + name + "): " + c); 369 } 358 370 359 371 // 5. Delegate to parent class loader if it hasn't been done 360 if (c == null && !delegateFirst) c = loadClassInternal(parent, name); 361 if (log.isDebugEnabled()) log.debug("parent class (" + name + "): " + c); 372 if (c == null && !delegateFirst) 373 { 374 c = loadClassInternal(parent, name); 375 if (log.isDebugEnabled()) log.debug("parent class (" + name + "): " + c); 376 } 377 378 // 6. Side-load from proxied JAR files (eg. other extensions) 379 Iterator<JarClassLoaderProxy> it = proxyLoaders.iterator(); 380 while (c == null && it.hasNext()) 381 { 382 JarClassLoaderProxy proxyLoader = it.next(); 383 c = proxyLoader.findClass(name); 384 if (log.isDebugEnabled()) log.debug("proxy class (" + proxyLoader.jarPath + "; " + name + "): " + c); 385 } 362 386 363 387 if (c == null) … … 528 552 if (followClassPath && manifest != null) 529 553 { 554 File directory = file.getParentFile(); 530 555 Attributes attr = manifest.getMainAttributes(); 531 556 if (attr != null) … … 540 565 if (cps[i] != null && !cps[i].trim().equals("")) 541 566 { 542 File classPathFile = new File( file.getParent(), cps[i]);567 File classPathFile = new File(directory, cps[i]); 543 568 if (!classPathFile.exists()) 544 569 { … … 573 598 } 574 599 } 600 loadJarFile(classPathFile, false); 575 601 } 576 loadJarFile(classPathFile, false); 602 else 603 { 604 proxyLoaders.add(new JarClassLoaderProxy(classPathFile.getAbsolutePath())); 605 } 577 606 } 578 607 } … … 728 757 } 729 758 } 759 760 /** 761 A proxy class loader is typically needed when one extension 762 depends on another extension. The proxy is needed since 763 we want to use lazy initialization of the other class loaders. 764 They may not be needed immediately. The proxy will also make it 765 possible to avoid infinite recursion in case two extensions 766 depend on each other. 767 <p> 768 769 Once a real class loader has been aquired it will be kept 770 until the main class loader is discared. Note that the 771 {@link JarClassLoader#hasChanged(boolean)} is not used for 772 automatic reloading since that may cause class-cast exceptions. 773 <p> 774 775 The proxy is also used to limit the search for classes to 776 classes that are directly handled directly by the other class 777 loader. The system and parent class loaders are not searched again 778 since they are already searched in the main class loader. 779 780 @since 3.10 781 */ 782 static class JarClassLoaderProxy 783 { 784 785 final String jarPath; 786 private JarClassLoader loader; 787 private boolean isInitialized; 788 789 /** 790 Creates a proxy class loader for the given JAR file. 791 */ 792 JarClassLoaderProxy(String jarPath) 793 { 794 this.jarPath = jarPath; 795 this.isInitialized = false; 796 } 797 798 /** 799 Initialize the proxy. 800 */ 801 private synchronized void init() 802 { 803 if (isInitialized) return; 804 if (log.isDebugEnabled()) log.debug("JarClassLoaderProxy.init[" + jarPath + "]"); 805 806 try 807 { 808 loader = (JarClassLoader)JarClassLoader.getInstance(jarPath, true); 809 } 810 catch (IOException ex) 811 {} 812 isInitialized = true; 813 } 814 815 816 Class<?> findClass(String name) 817 { 818 if (log.isDebugEnabled()) log.debug("JarClassLoaderProxy.findClass[" + jarPath + "]: " + name); 819 if (!isInitialized) init(); 820 821 Class<?> c = null; 822 if (loader != null) 823 { 824 try 825 { 826 // 1. Check if the class has already been loaded 827 c = loader.findLoadedClass(name); 828 if (log.isDebugEnabled()) log.debug("JarClassLoaderProxy.findClass[" + jarPath + "]: loaded class (" + name + "): " + c); 829 830 // 2. Otherwise try to load the class without searching parent or system class loaders 831 if (c == null) 832 { 833 c = loader.findClass(name); 834 if (log.isDebugEnabled()) log.debug("JarClassLoaderProxy.findClass[" + jarPath + "]: found class (" + name + "): " + c); 835 } 836 } 837 catch (ClassNotFoundException ex) 838 {} 839 } 840 return c; 841 } 842 } 730 843 } -
trunk/src/test/net/sf/basedb/test/extension/jar3/Three.java
r7190 r7192 35 35 { 36 36 37 private final One one; 38 private final Two two; 39 37 40 public Three() 38 {} 41 { 42 this.one = new One(); 43 this.two = new Two(); 44 } 39 45 40 46 @Override 41 47 public String getTitle() 42 48 { 43 return new One().getTitle() + "+" + new Two().getTitle() + "=Three";49 return one.getTitle() + "+" + two.getTitle() + "=Three"; 44 50 } 45 51 … … 53 59 public int getType() 54 60 { 55 return 3;61 return one.getType()+two.getType(); 56 62 } 57 63
Note: See TracChangeset
for help on using the changeset viewer.