Cannot run 2.0-RC1, NoClassDefFoundDefError

I think you don’t get the hit as you are scanning a much smaller liquibase jar.  In my case the liquibase classes are put into a possibly much larger (20 - 200 MB) jar so that creates a performance hit.

I understand your motivation and it would work fine except for the performance issue in our scenario.  These jar files are patches for a system that could have hundreds of patches, if there is a 3+ minute overhead on each patch install it will have a detrimental effect.

I have attached a screenshot of the VisualVm profiling output listing hotspot methods.

Also attached is the visual VM snapshot for the execution.

Looks like ResolverUtil.listClassResources is the main culprit.  If you open the snapshot in VisualVM which you can find in any 1.6 JDK under the bin directory (jvisualvm.exe), you will see that it is executed at different times during the processing, could be that it runs when it shouldn’t?

Btw. you have to use the Load function in visualvm to load the profiler snapshot (*.nps).  The relevant thread is the Izpack Unpacker thread.

This is currently just a guess, but shouldn’t any find methods check if there are any existing ‘matches’ before checking the jar again?  If I have time I’ll play around with this although today is D DAY.

That hotspot list is much different than the one I was seeing.  Are you attempting to load jars over a network, or something else that is slower than normal?

I put a simple fix in to cache classnames by jar file that should help a bit at least.  Are you able to try building from trunk and see how the new version compares?

Nathan

Yes I think the issue is that my Liquibase classes are mixed into a large jar with other classes, so it takes long to load every time maybe?

I will build and give feedback as soon as possible, thanks.

I swapped out the implementation for a different one.  Make sure you test it with the newest code from trunk

Nathan

I have attached some profiler snapshots using the latest code.  There is a slight improvement from the last one.

Having run this on a VM from external USB disk and on internal harddisk I don’t see any difference in performance.  Also I tried moving the liquibase classes to be closer to the beginning of the jar file with no success. 

DefaultPackageScanClassResolver is now the busiest one.  Maybe there is something inherently slow in using a JarInputStream.  Do the java classloader use the same principle?

I made another performance change based on your most recent snapshot.  I think the classloader uses the came prinicpal, but we end up reading the jar file a few times which gets expensive for a large jar, apparently. 

It should now just read through the jar one time.  Could you try it with a new trunk build?

Nathan

First look it seems that DatabaseFactory.getInstance().findDefaultDriver(url) returns null.

This is probably the reason for Alexis’s issue with the Logger:

The loadImplementationsInJar will only look in the jar for the very first package in packagesToScan as after the first package is scanned there will be an entry in classesByJarUrl and it will skip scanning for other packages.

Btw. if it did it looks like it will scan the jar as many times as there are packages to scan for.

I’ve written some code which I will attach soon, it doesn’t work yet but the idea is the following:

  1. findImplementations is called with the interface to implement.
  2. It checks if classesByJarUrl is empty.  If it is it goes and loads classesByUrl with all classes at the packages and it does so by only scanning the jar once.
  3. after 2) findImplementations processes classesByJarUrl and applies the addIfMatching test to a Set of classes which it returns to the calling code.

I think the logic is right, even though its not completely working yet and it breaks a lot of unit tests.

As mentioned in previous post I have attached my first non-working attempt at implementing the interface implementations detailed in previous post.

I have not yet traced it to see what is actually happening, will probably only be doing so in 14 hours.

I’m wondering if a lot of the logic you added isn’t really necessary.  Judging by your hotspot list before, it was from reading the jar that was taking the time.  My change with classesByJarUrl gets populated when a jar is first checked for a package.  Each subsequent check for another package doesn’t need to rescan the jar for classes, it can just read from the map. 

There was a bug (which everyone found) that I was only saving classes in classesByJarUrl that matched the first package.  The fix was to populate classesByJarUrl with all classes the first time, then check the package as part of the test.

Could you do a performance test with the standard implementation, and see how it does?

Nathan

I’ll be happy to use the standard implementation as I’m a bit crunched for time :slight_smile:

The reason why I wrote the code the way I did was that it seemed as if the iteration through the package names were at the wrong side of the processing.  For each package it would call loadImplementationsInJar which would then iterate through the whole jar for that single package (unless you’ve changed it with the fix for that issue).  It looked hard to fix it in loadImplementationsInJar with minimum changes which is why the big overhaul.

Do you have a svn reference for the fix for the problem of not all packages being added to classesByJarUrl?

I’ve got latest HEAD and I’m still getting that behavior.

It should have been fixed in revision 1657.

I agree that it’s not the most efficient, and a single scan through each jar would probably be best, but since it’s borrowed code, I didn’t want to make many changes, so future updates and comparisons to their codebase would be easier.  It still iterates through all the class names in each jar for each package, but the classesByJarUrl should keep us from having to do the expensive jar reading operation.

Nathan

I see now the change and you’re right it should add all classes to classesByJarUrl.  Now I’m really confused as to why its not finding my database driver.

Ed: Ok, I see we are now on rc6, will see if using the right jar fixes it :slight_smile:

Ok, I think the fix did it.  I have attached a profiling snapshot.

Great, thanks for the help troubleshooting.

Nathan