BAEL-4615: Create and Detect Memory Leak in Java (#14060)
This commit is contained in:
parent
2091146702
commit
7317f0816d
|
@ -5,3 +5,4 @@ This module contains articles about performance of Java applications
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Possible Root Causes for High CPU Usage in Java](https://www.baeldung.com/java-high-cpu-usage-causes)
|
- [Possible Root Causes for High CPU Usage in Java](https://www.baeldung.com/java-high-cpu-usage-causes)
|
||||||
- [External Debugging With JMXTerm](https://www.baeldung.com/java-jmxterm-external-debugging)
|
- [External Debugging With JMXTerm](https://www.baeldung.com/java-jmxterm-external-debugging)
|
||||||
|
- [Create and Detect Memory Leaks in Java](https://www.baeldung.com/java-create-detect-memory-leaks)
|
||||||
|
|
|
@ -13,4 +13,11 @@
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.datafaker</groupId>
|
||||||
|
<artifactId>datafaker</artifactId>
|
||||||
|
<version>1.6.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.lapsedlistener;
|
||||||
|
|
||||||
|
import static com.baeldung.lapsedlistener.UserGenerator.generateUser;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class LapsedListenerRunner {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(LapsedListenerRunner.class);
|
||||||
|
private static final MovieQuoteService movieQuoteService = new MovieQuoteService();
|
||||||
|
|
||||||
|
static {
|
||||||
|
movieQuoteService.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
while (true) {
|
||||||
|
User user = generateUser();
|
||||||
|
logger.debug("{} logged in", user.getName());
|
||||||
|
user.subscribe(movieQuoteService);
|
||||||
|
userUsingService();
|
||||||
|
logger.debug("{} logged out", user.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void userUsingService() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(10);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.baeldung.lapsedlistener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import net.datafaker.Faker;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class MovieQuoteService implements Subject {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MovieQuoteService.class);
|
||||||
|
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||||
|
private final List<Observer> observers = new ArrayList<>();
|
||||||
|
private final Faker faker = new Faker();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attach(Observer observer) {
|
||||||
|
logger.debug("Current number of subscribed users: {}", observers.size());
|
||||||
|
observers.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detach(Observer observer) {
|
||||||
|
observers.remove(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyObservers() {
|
||||||
|
String quote = faker.movie().quote();
|
||||||
|
logger.debug("New quote: {}", quote);
|
||||||
|
for (Observer observer : observers) {
|
||||||
|
logger.debug("Notifying user: {}", observer);
|
||||||
|
observer.update(quote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
scheduler.scheduleAtFixedRate(this::notifyObservers, 0, 1, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int numberOfSubscribers() {
|
||||||
|
return observers.size();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.lapsedlistener;
|
||||||
|
|
||||||
|
public interface Observer {
|
||||||
|
void update(String latestNews);
|
||||||
|
|
||||||
|
void subscribe(Subject subject);
|
||||||
|
|
||||||
|
void unsubscribe(Subject subject);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.lapsedlistener;
|
||||||
|
|
||||||
|
public interface Subject {
|
||||||
|
void attach(Observer observer);
|
||||||
|
|
||||||
|
void detach(Observer observer);
|
||||||
|
|
||||||
|
void notifyObservers();
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.baeldung.lapsedlistener;
|
||||||
|
|
||||||
|
public class User implements Observer {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String email;
|
||||||
|
private final String phone;
|
||||||
|
private final String street;
|
||||||
|
private final String city;
|
||||||
|
private final String state;
|
||||||
|
private final String zipCode;
|
||||||
|
|
||||||
|
public User(String name, String email, String phone, String street, String city, String state, String zipCode) {
|
||||||
|
this.name = name;
|
||||||
|
this.email = email;
|
||||||
|
this.phone = phone;
|
||||||
|
this.street = street;
|
||||||
|
this.city = city;
|
||||||
|
this.state = state;
|
||||||
|
this.zipCode = zipCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhone() {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getZipCode() {
|
||||||
|
return zipCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(final String quote) {
|
||||||
|
// user got updated with a new quote
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void subscribe(final Subject subject) {
|
||||||
|
subject.attach(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unsubscribe(final Subject subject) {
|
||||||
|
subject.detach(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "User [name=" + name + "]";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.lapsedlistener;
|
||||||
|
|
||||||
|
import net.datafaker.Faker;
|
||||||
|
|
||||||
|
public class UserGenerator {
|
||||||
|
|
||||||
|
private UserGenerator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Faker faker = new Faker();
|
||||||
|
|
||||||
|
public static User generateUser() {
|
||||||
|
String name = faker.name().fullName();
|
||||||
|
String email = faker.internet().emailAddress();
|
||||||
|
String phone = faker.phoneNumber().cellPhone();
|
||||||
|
String street = faker.address().streetAddress();
|
||||||
|
String city = faker.address().city();
|
||||||
|
String state = faker.address().state();
|
||||||
|
String zipCode = faker.address().zipCode();
|
||||||
|
return new User(name, email, phone, street, city, state, zipCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.baeldung.lapsedlistener;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class MovieQuoteServiceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenSubscribeToService_thenServiceHasOneSubscriber() {
|
||||||
|
MovieQuoteService service = new MovieQuoteService();
|
||||||
|
service.attach(UserGenerator.generateUser());
|
||||||
|
assertEquals(1, service.numberOfSubscribers());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenUnsubscribeFromService_thenServiceHasNoSubscribers() {
|
||||||
|
MovieQuoteService service = new MovieQuoteService();
|
||||||
|
User user = UserGenerator.generateUser();
|
||||||
|
service.attach(user);
|
||||||
|
service.detach(user);
|
||||||
|
assertEquals(0, service.numberOfSubscribers());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue