Skip to content
This repository has been archived by the owner on Jun 7, 2021. It is now read-only.

APEXCORE-767.set parent classloader in StramAppLauncher.loadDependencies #563

Conversation

florianschmidt1994
Copy link
Contributor

@florianschmidt1994 florianschmidt1994 commented Jul 21, 2017

Following below is my understanding of the problem (should be probably taken with a grain of salt, as I just started digging in to the apex-core codebase):

StramAppLauncher.loadDependencies is called multiple times when starting
an application via the apex-cli with the -local option. In each of the
calls to loadDependencies, the contextClassLoader of the current thread
would be replaced with a new instance of URLClassLoader (which has no
parent class loader set).

This can lead to issues, e.g. when one acquires the current
contextClassLauncher, loads a class with it and tries to cast it to a
class which was loaded with a previous instance of the contextClassLoader,
resulting in a ClassCastException.

An example of this bug can be seen in APEXMALHAR-2511

The changes in this pr fix this by passing the parent class loader
for each new instance of URLClassLoader to the current
contextClassLoader

I am still in the process of figuring how the StramAppLauncher works and why the dependencies get loaded multiple times in the first place, is this intended behavior? Otherwise I could also look into what is going on there as well. (See discussion on JIRA)

@vrozov
Copy link
Member

vrozov commented Jul 22, 2017

Test this please

@tweise
Copy link
Contributor

tweise commented Jul 22, 2017

@florianschmidt1994 please change your git settings so that the email address matches your github profile, otherwise the commits won't be linked.

@vrozov
Copy link
Member

vrozov commented Jul 22, 2017

Please include JIRA info into commit message as well.

URLClassLoader cl = URLClassLoader.newInstance(launchDependencies.toArray(new URL[launchDependencies.size()]));
URL[] dependencies = launchDependencies.toArray(new URL[launchDependencies.size()]);

ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can created URL class loaders be cached, it should not be necessary to create a new class loader each time loadDependencies() is called.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly. The dependencies can change though, between original introspection of the app package and actual launch, for example when the application adds additional jar files to LIBRARY_JARS. And as commented on the JIRA, class loaders also need to be cleaned up..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestion is to cache URL class loaders on the instance of the StramAppLauncher instance to avoid unnecessary instantiation of URL class loaders with the same dependencies. If dependencies change, the cache should be cleared.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue to be addressed here it that additional dependencies need to be added to the existing class loader, hence chaining with previous class loader. Avoiding repeated instantiation with exactly same dependencies is an optimization, first we should get the functional issue addressed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it will be OK just to fix the functional issue in this PR and have JIRA open with optimization request it will be great if the contributor is willing to put a little bit more effort and implement the optimization. Said that I will not stop any other committer from merging the PR if it looks sufficient.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not suggesting to merge the PR just yet, I wan't to make sure we actually resolve the issue before applying optimizations. For example, the PR needs to address removing the prior context class loader before the next application is launched.

@vrozov
Copy link
Member

vrozov commented Jul 24, 2017

@florianschmidt1994 Please consider adding a unit test.

@florianschmidt1994 florianschmidt1994 force-pushed the APEXCORE-767.duplicate-classloading-in-cli-local branch from 4ce4858 to 759e5c3 Compare July 25, 2017 00:46
@florianschmidt1994 florianschmidt1994 force-pushed the APEXCORE-767.duplicate-classloading-in-cli-local branch 4 times, most recently from 9316a89 to 3fa4b14 Compare August 4, 2017 16:58
@tweise
Copy link
Contributor

tweise commented Sep 4, 2017

@florianschmidt1994 please rebase the PR and see if the CI build passes. Also change the author on the commit to reflect your github account: http://apex.apache.org/contributing.html#github-and-git

@tweise tweise closed this Oct 3, 2017
@tweise tweise reopened this Oct 3, 2017
@@ -0,0 +1,61 @@
/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with the standard license header.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I replace this with our license header when I de facto just copy and pasted this code from stack overflow?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed at all, can you not use ExecutorService instead? https://stackoverflow.com/a/40605786/3148138

Regarding license header, all files have to have the ASL header. As to whether you can copy the code or not:

https://meta.stackexchange.com/questions/271080/the-mit-license-clarity-on-using-code-on-stack-overflow-and-stack-exchange

You don’t have to include the full MIT License in your code base. Contributors agree to give code users permission to ignore the MIT License’s notice preservation requirement, as long as users give reasonable attribution upon request of the copyright holder (or Stack Exchange on behalf of the contributor). This optional exception to the MIT License will live in our terms of service.

@tweise
Copy link
Contributor

tweise commented Oct 3, 2017

I have verified that this fixes APEXMALHAR-2511. Please rebase, fix license header and commit author.

@tweise
Copy link
Contributor

tweise commented Oct 9, 2017

@florianschmidt1994 any update?

@florianschmidt1994
Copy link
Contributor Author

There are still some minor details that I wanted to verify, I'll take care of this during the course of the week

@florianschmidt1994 florianschmidt1994 force-pushed the APEXCORE-767.duplicate-classloading-in-cli-local branch from 3fa4b14 to de01bef Compare October 11, 2017 23:34
@florianschmidt1994
Copy link
Contributor Author

florianschmidt1994 commented Oct 11, 2017

Occurence of loadDependencies() Context Proposed calls to resetContextClassLoader()
AppPackage#processAppDirectory line 470 Processing the app directory  ???
StramAppLauncher#runLocal line 533 Running the app in local mode Nothing, is covered by outer resetContextLoader of launch command
StramAppLauncher#launchApp line 602 Running the app on the cluster Nothing, is covered by outer resetContextLoader of launch command
StramClientUtils.jsonFileToAppInfo line 933 Convert jsonFile to AppInfo  Used in the context of processAppDirectory, see above and processAppDirectory of ConfigPackage  ???
YarnLauncherImpl#launchApp line 73 Launch app  ???

I added this table from JIRA with cases where potentiall calls to resetContextClassLoader might be necessary. Unfortunately some of the details of whats happening in the cases marked with ??? are still a little bit unclear to me, which is why I did not modify anything there.

@tweise
Copy link
Contributor

tweise commented Oct 12, 2017

YarnLauncherImpl#launchApp - before the return
StramClientUtils.jsonFileToAppInfo - that's murky because in one case the dependencies are loaded by the caller and in the other case not. I think reset should be added to the processAppDirectory methods.

@tweise
Copy link
Contributor

tweise commented Nov 13, 2017

@florianschmidt1994 any update?

StramAppLauncher.loadDependencies is called multiple times when starting
an application via the apex-cli with the -local option. In each of the
calls to loadDependencies, the contextClassLoader of the current thread
would be replaced with a new instance of URLClassLoader (which has no
parent class loader set).

This can lead to issues, e.g. when one aquires the current
contextClassLauncher, loads a class with it and tries to cast it to a
class which was loaded with a previous version of the contextClassLoader,
resulting in a ClassCastException.

An example of this bug can be seen in APEXMALHAR-2511

The changes in this commit fix this by passing the parent class loader
for each new instance of URLClassLoader to the current
contextClassLoader
@florianschmidt1994 florianschmidt1994 force-pushed the APEXCORE-767.duplicate-classloading-in-cli-local branch from de01bef to 34d71f4 Compare November 17, 2017 13:22
@florianschmidt1994
Copy link
Contributor Author

The changes were incorporated as discussed and it should be looking good by now. Unfortunately I don't have a setup up and running to test this right now, but if wanted I could sit down and verify the changes one last time in the near future. Otherwise feel free to merge (if the build passes ;) )

@asfgit
Copy link

asfgit commented Nov 17, 2017

FAILURE

--none--

@tweise
Copy link
Contributor

tweise commented Nov 17, 2017

test this please

@asfgit
Copy link

asfgit commented Nov 17, 2017

FAILURE

--none--

@tweise
Copy link
Contributor

tweise commented Nov 18, 2017

test this please

@asfgit
Copy link

asfgit commented Nov 18, 2017

SUCCESS

--none--

@tweise tweise merged commit b3911c3 into apache:master Nov 19, 2017
@florianschmidt1994 florianschmidt1994 deleted the APEXCORE-767.duplicate-classloading-in-cli-local branch November 19, 2017 18:01
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
4 participants