cloudfoundry / cloudfoundry/cf-java-client

Memory leak since version `5.8.0`

Aperta
#1,186 2 commenti 1 reazione 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Lingua principale
Java
Stelle
334
Fork
319
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Descrizione

The following code results in a memory leak:

Main.java
package org.example;

import org.cloudfoundry.client.v2.users.GetUserResponse;
import org.cloudfoundry.client.v3.roles.RoleType;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.List;

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world!");

        SpringApplication.run(Main.class, args);

        triggerCalls();
    }

    public static void triggerCalls() {
        CloudFoundryService cloudFoundryService = new CloudFoundryService();

        for (int i = 0; i < 100; i++) {
            try {
                GetUserResponse getUserResponse = cloudFoundryService.getUser("c33c0489-2f84-4ddc-9b6a-e4f73c8be628");
                System.out.println("Fetch " + i + " : " + getUserResponse.getEntity().getUsername());

                List<RoleType> roleTypes = cloudFoundryService.getUserRoles();

            } catch (Exception e) {
            }
        }

        System.out.println("DONE");

    }
}
CloudFoundryService.java
package org.example;

import org.cloudfoundry.client.v2.users.GetUserRequest;
import org.cloudfoundry.client.v2.users.GetUserResponse;
import org.cloudfoundry.client.v3.roles.ListRolesRequest;
import org.cloudfoundry.client.v3.roles.RoleResource;
import org.cloudfoundry.client.v3.roles.RoleType;
import org.cloudfoundry.reactor.DefaultConnectionContext;
import org.cloudfoundry.reactor.client.ReactorCloudFoundryClient;
import org.cloudfoundry.reactor.tokenprovider.PasswordGrantTokenProvider;

import java.util.List;
import java.util.stream.Collectors;

public class CloudFoundryService {

    private String user = "user";
    private String password = "1234";

    public GetUserResponse getUser(String userId) {
        return this.getClient().users().get(GetUserRequest.builder().userId(userId).build()).block();
    }

    public List<RoleType> getUserRoles() {
        return this.getClient().rolesV3().list(ListRolesRequest.builder().build())
                .map(userRoleListResponse -> {
                    return userRoleListResponse.getResources().stream()
                            .map(RoleResource::getType)
                            .collect(Collectors.toList());
                })
                .block();

    }

    ReactorCloudFoundryClient getClient() {
        return ReactorCloudFoundryClient.builder()
                .connectionContext(this.connectionContext())
                .tokenProvider(this.tokenProvider())
                .build();
    }

    DefaultConnectionContext connectionContext() {
        return DefaultConnectionContext.builder()
                .apiHost("api.domain.com")
                .build();
    }

    PasswordGrantTokenProvider tokenProvider() {
        return PasswordGrantTokenProvider.builder()
                .password(this.password)
                .username(this.user)
                .build();
    }
}

Here's a stack trace:

Stacktrace
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR Exception in thread "main" java.lang.reflect.InvocationTargetException
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/java.lang.reflect.Method.invoke(Unknown Source)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.springframework.boot.loader.Launcher.launch(Launcher.java:108)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR Caused by: java.lang.OutOfMemoryError: Cannot reserve 49152 bytes of direct buffer memory (allocated: 10444808, limit: 10485760)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/java.nio.Bits.reserveMemory(Unknown Source)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/java.nio.DirectByteBuffer.<init>(Unknown Source)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/java.nio.ByteBuffer.allocateDirect(Unknown Source)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.unix.Buffer.allocateDirectWithNativeOrder(Buffer.java:40)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.epoll.EpollEventArray.<init>(EpollEventArray.java:58)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.epoll.EpollEventLoop.<init>(EpollEventLoop.java:95)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.epoll.EpollEventLoopGroup.newChild(EpollEventLoopGroup.java:187)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.epoll.EpollEventLoopGroup.newChild(EpollEventLoopGroup.java:37)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:84)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:60)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.util.concurrent.MultithreadEventExecutorGroup.<init>(MultithreadEventExecutorGroup.java:49)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.MultithreadEventLoopGroup.<init>(MultithreadEventLoopGroup.java:59)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.epoll.EpollEventLoopGroup.<init>(EpollEventLoopGroup.java:114)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.epoll.EpollEventLoopGroup.<init>(EpollEventLoopGroup.java:101)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at io.netty.channel.epoll.EpollEventLoopGroup.<init>(EpollEventLoopGroup.java:78)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.resources.DefaultLoopEpoll.newEventLoopGroup(DefaultLoopEpoll.java:93)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.resources.DefaultLoopResources.cacheNativeServerLoops(DefaultLoopResources.java:254)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.resources.DefaultLoopResources.cacheNativeClientLoops(DefaultLoopResources.java:219)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.resources.DefaultLoopResources.onClient(DefaultLoopResources.java:139)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.transport.NameResolverProvider.newNameResolverGroup(NameResolverProvider.java:473)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.transport.ClientTransportConfig.lambda$getOrCreateResolver$0(ClientTransportConfig.java:240)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(Unknown Source)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.internal.util.MapUtils.computeIfAbsent(MapUtils.java:46)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.transport.ClientTransportConfig.getOrCreateResolver(ClientTransportConfig.java:239)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.transport.ClientTransport.runOn(ClientTransport.java:352)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.transport.ClientTransport.runOn(ClientTransport.java:42)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at reactor.netty.transport.Transport.runOn(Transport.java:249)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.cloudfoundry.reactor._DefaultConnectionContext.configureHttpClient(_DefaultConnectionContext.java:265)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.cloudfoundry.reactor._DefaultConnectionContext.getHttpClient(_DefaultConnectionContext.java:105)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.cloudfoundry.reactor.DefaultConnectionContext.access$2201(DefaultConnectionContext.java:26)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.cloudfoundry.reactor.DefaultConnectionContext$InitShim.getHttpClient(DefaultConnectionContext.java:126)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.cloudfoundry.reactor.DefaultConnectionContext.<init>(DefaultConnectionContext.java:83)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.cloudfoundry.reactor.DefaultConnectionContext.<init>(DefaultConnectionContext.java:26)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.cloudfoundry.reactor.DefaultConnectionContext$Builder.build(DefaultConnectionContext.java:1167)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.example.CloudFoundryService.connectionContext(CloudFoundryService.java:45)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.example.CloudFoundryService.getClient(CloudFoundryService.java:37)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.example.CloudFoundryService.getUser(CloudFoundryService.java:21)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.example.Main.triggerCalls(Main.java:25)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR at org.example.Main.main(Main.java:17)
24/07/2023, 08:31:01 [APP/PROC/WEB/0] ERR ... 8 more

It is not reproducible locally (macOS). We deploy this as a CloudFoundry app (linux).

It is not reproducible with version 5.7.0.

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con il riproduttore fornito di Main.java e CloudFoundryService.java, quindi segui i frame dello stack di getClient(), connectionContext() e DefaultConnectionContext nel report. Esegui le chiamate ripetute su Linux o Cloud Foundry e confronta il comportamento con le versioni 5.7.0 e 5.8.0. Il lavoro è completato quando le chiamate ripetute non esauriscono più la memoria dei buffer diretti e la regressione è coperta da una verifica riproducibile.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
java
Ambito
api, backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.