@@ -91,6 +91,54 @@ private[spark] object ClosureCleaner extends Logging {
9191 (seen - obj.getClass).toList
9292 }
9393
94+ /** Initializes the accessed fields for outer classes and their super classes. */
95+ private def initAccessedFields (
96+ accessedFields : Map [Class [_], Set [String ]],
97+ outerClasses : Seq [Class [_]]): Unit = {
98+ for (cls <- outerClasses) {
99+ var currentClass = cls
100+ assert(currentClass != null , " The outer class can't be null." )
101+
102+ while (currentClass != null ) {
103+ accessedFields(currentClass) = Set .empty[String ]
104+ currentClass = currentClass.getSuperclass()
105+ }
106+ }
107+ }
108+
109+ /** Sets accessed fields for given class in clone object based on given object. */
110+ private def setAccessedFields (
111+ outerClass : Class [_],
112+ clone : AnyRef ,
113+ obj : AnyRef ,
114+ accessedFields : Map [Class [_], Set [String ]]): Unit = {
115+ for (fieldName <- accessedFields(outerClass)) {
116+ val field = outerClass.getDeclaredField(fieldName)
117+ field.setAccessible(true )
118+ val value = field.get(obj)
119+ field.set(clone, value)
120+ }
121+ }
122+
123+ /** Clones a given object and sets accessed fields in cloned object. */
124+ private def cloneAndSetFields (
125+ parent : AnyRef ,
126+ obj : AnyRef ,
127+ outerClass : Class [_],
128+ accessedFields : Map [Class [_], Set [String ]]): AnyRef = {
129+ val clone = instantiateClass(outerClass, parent)
130+
131+ var currentClass = outerClass
132+ assert(currentClass != null , " The outer class can't be null." )
133+
134+ while (currentClass != null ) {
135+ setAccessedFields(currentClass, clone, obj, accessedFields)
136+ currentClass = currentClass.getSuperclass()
137+ }
138+
139+ clone
140+ }
141+
94142 /**
95143 * Clean the given closure in place.
96144 *
@@ -202,9 +250,8 @@ private[spark] object ClosureCleaner extends Logging {
202250 logDebug(s " + populating accessed fields because this is the starting closure " )
203251 // Initialize accessed fields with the outer classes first
204252 // This step is needed to associate the fields to the correct classes later
205- for (cls <- outerClasses) {
206- accessedFields(cls) = Set .empty[String ]
207- }
253+ initAccessedFields(accessedFields, outerClasses)
254+
208255 // Populate accessed fields by visiting all fields and methods accessed by this and
209256 // all of its inner closures. If transitive cleaning is enabled, this may recursively
210257 // visits methods that belong to other classes in search of transitively referenced fields.
@@ -250,13 +297,8 @@ private[spark] object ClosureCleaner extends Logging {
250297 // required fields from the original object. We need the parent here because the Java
251298 // language specification requires the first constructor parameter of any closure to be
252299 // its enclosing object.
253- val clone = instantiateClass(cls, parent)
254- for (fieldName <- accessedFields(cls)) {
255- val field = cls.getDeclaredField(fieldName)
256- field.setAccessible(true )
257- val value = field.get(obj)
258- field.set(clone, value)
259- }
300+ val clone = cloneAndSetFields(parent, obj, cls, accessedFields)
301+
260302 // If transitive cleaning is enabled, we recursively clean any enclosing closure using
261303 // the already populated accessed fields map of the starting closure
262304 if (cleanTransitively && isClosure(clone.getClass)) {
@@ -395,8 +437,15 @@ private[util] class FieldAccessFinder(
395437 if (! visitedMethods.contains(m)) {
396438 // Keep track of visited methods to avoid potential infinite cycles
397439 visitedMethods += m
398- ClosureCleaner .getClassReader(cl).accept(
399- new FieldAccessFinder (fields, findTransitively, Some (m), visitedMethods), 0 )
440+
441+ var currentClass = cl
442+ assert(currentClass != null , " The outer class can't be null." )
443+
444+ while (currentClass != null ) {
445+ ClosureCleaner .getClassReader(currentClass).accept(
446+ new FieldAccessFinder (fields, findTransitively, Some (m), visitedMethods), 0 )
447+ currentClass = currentClass.getSuperclass()
448+ }
400449 }
401450 }
402451 }
0 commit comments