wangbing505 commented on issue #12456:
URL: https://github.com/apache/seatunnel/issues/12456#issuecomment-5862488423

   Thank you for your response.
   
   ### ClassLoader comparison before and after job submission
   
   Before submitting the job:
   
   ```text
   [arthas@9]$ classloader
    name                                       numberOfInstances  
loadedCountTotal
    sun.misc.Launcher$AppClassLoader           1                  7657
    BootstrapClassLoader                       1                  3454
    com.taobao.arthas.agent.ArthasClassloader  1                  2364
    sun.reflect.DelegatingClassLoader          152                152
    sun.misc.Launcher$ExtClassLoader           1                  42
    sun.reflect.misc.MethodUtil                1                  1
   
   Affect(row-cnt:6) cost in 11 ms.
   ```
   
   After submitting the first job:
   
   ```text
   [arthas@9]$ classloader
    name                                                                      
numberOfInstances  loadedCountTotal
    sun.misc.Launcher$AppClassLoader                                          1 
                 10586
    BootstrapClassLoader                                                      1 
                 3693
    com.taobao.arthas.agent.ArthasClassloader                                 1 
                 2364
    org.apache.seatunnel.engine.common.loader.SeaTunnelChildFirstClassLoader  2 
                 2320
    sun.reflect.DelegatingClassLoader                                         
245                245
    sun.misc.Launcher$ExtClassLoader                                          1 
                 44
    sun.reflect.misc.MethodUtil                                               1 
                 1
   
   Affect(row-cnt:7) cost in 13 ms.
   ```
   
   After submitting another job:
   
   ```text
   [arthas@9]$ classloader
    name                                                                      
numberOfInstances  loadedCountTotal
    sun.misc.Launcher$AppClassLoader                                          1 
                 10610
    org.apache.seatunnel.engine.common.loader.SeaTunnelChildFirstClassLoader  4 
                 4643
    BootstrapClassLoader                                                      1 
                 3694
    com.taobao.arthas.agent.ArthasClassloader                                 1 
                 2367
    sun.reflect.DelegatingClassLoader                                         
271                271
    sun.misc.Launcher$ExtClassLoader                                          1 
                 44
    sun.reflect.misc.MethodUtil                                               1 
                 1
   
   Affect(row-cnt:7) cost in 12 ms.
   ```
   
   After another 10 minutes, with no new jobs submitted, the number of 
`SeaTunnelChildFirstClassLoader` instances did not increase:
   
   ```text
   [arthas@9]$ classloader
    name                                                                      
numberOfInstances  loadedCountTotal
    sun.misc.Launcher$AppClassLoader                                          1 
                 10655
    org.apache.seatunnel.engine.common.loader.SeaTunnelChildFirstClassLoader  4 
                 4645
    BootstrapClassLoader                                                      1 
                 3694
    com.taobao.arthas.agent.ArthasClassloader                                 1 
                 2367
    sun.reflect.DelegatingClassLoader                                         
271                271
    sun.misc.Launcher$ExtClassLoader                                          1 
                 44
    sun.reflect.misc.MethodUtil                                               1 
                 1
   
   Affect(row-cnt:7) cost in 18 ms.
   ```
   
   This seems to indicate that the `SeaTunnelChildFirstClassLoader` instances 
are primarily created when new jobs are submitted, rather than continuously 
increasing during idle periods.
   
   ### Job information
   
   The Job ID is:
   
   ```text
   23184458863328
   ```
   
   I used the following command to check the job status across the cluster:
   
   ```text
   ./bin/seatunnel.sh -j 23184458863328
   ```
   
   The result was:
   
   ```json
   {
     "jobId": 23184458863328,
     "jobName": "local_test_mongo2hive_0615_08_copy_copy",
     "jobStatus": "FINISHED",
     "submitTime": 1790558985229,
     "startTime": 1790558986875,
     "finishTime": 1790558992144,
     "pipelineStateMapperMap": {
       "PipelineLocation(jobId=23184458863328, pipelineId=1)": {
         "pipelineStatus": "FINISHED",
         "executionStateMap": {
           "TaskGroupLocation{jobId=23184458863328, pipelineId=1, 
taskGroupId=1}": "FINISHED",
           "TaskGroupLocation{jobId=23184458863328, pipelineId=1, 
taskGroupId=2}": "FINISHED",
           "TaskGroupLocation{jobId=23184458863328, pipelineId=1, 
taskGroupId=3}": "FINISHED"
         }
       }
     },
     "errorMessage": null,
     "project": "dataex_dev_project"
   }
   ```
   log message
   
   <img width="1634" height="210" alt="Image" 
src="https://github.com/user-attachments/assets/8f13c251-c22b-4e17-805d-a3c6e28394b6";
 />
   
   ### Relevant logs and MAT analysis
   
   I also took a heap dump at this point, then analyzed it using MAT.
   
   first
   <img width="1422" height="790" alt="Image" 
src="https://github.com/user-attachments/assets/1bd0c366-b324-40cb-bec7-1ea572b84bb8";
 />
   
   second
   <img width="1325" height="411" alt="Image" 
src="https://github.com/user-attachments/assets/6379748c-05d3-4eac-bcb0-fdcd2d05b919";
 />
   
   The first retained `ChildFirstClassLoader` is particularly difficult to deal 
with.
   
   I previously tried to explicitly clean up these references inside 
`releaseClassLoader`. However, after cleaning up one reference chain, another 
reference from a different Hadoop class appeared and retained the ClassLoader 
again.
   
   The current analysis shows the following:
   
   After removing A/B/C and checking the heap again, two new chains with 
essentially the same pattern appeared:
   
   * `CodecPool.compressorCounts`: this is still related to `CodecPool`, but 
this time it is a Guava `LocalCache` rather than a `java.util.Map`. Therefore, 
the previous `(Map)` cast and `removeClassKeyedEntriesLoadedBy` logic cannot 
cover this case. This appears to be exactly why the same type of reference 
shows up again in the latest MAT analysis.
   
   * `WritableComparator.comparators`: another Hadoop static registry that 
retains classes loaded by the child ClassLoader.
   
   There seem to be many long-lived Hadoop static structures whose keys are 
Classes loaded by the child ClassLoader, such as `SerializationFactory`, 
`Groups`, and others.
   
   The exact structures also vary depending on the Hadoop version. In some 
versions they are regular Maps, while in others they may be Guava caches. 
Handling each one individually would therefore require continuously adding 
special cases.
   
   After seeing the same pattern appear in multiple rounds of analysis, I think 
this is becoming an architectural signal rather than an isolated reference leak.
   
   Instead of continuing to remove individual references one by one, I am 
considering a more fundamental approach: making the Parquet compression-related 
classes be loaded by the parent ClassLoader, so that the keys in these 
long-lived Hadoop static registries are associated with the parent ClassLoader 
rather than the `SeaTunnelChildFirstClassLoader`. In that case, these static 
registries would no longer retain the SeaTunnel child ClassLoader.
   
   ### Questions
   
   Based on the above observations, do you have any recommended approaches for 
addressing this ClassLoader retention problem?
   
   In particular, I would like to understand whether we should:
   
   1. Continue cleaning up individual Hadoop static references during 
`releaseClassLoader`;
   2. Change the ClassLoader relationship so that certain Hadoop/Parquet 
classes are loaded by the parent ClassLoader;
   3. Focus on identifying and stopping engine-side threads such as 
`BufferPoolPruner` that retain the child ClassLoader;
   4. Or consider a more systematic lifecycle/design change for 
`SeaTunnelChildFirstClassLoader`.
   
   Any suggestions on the recommended direction would be greatly appreciated.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to