-
-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Ai auto update #3443
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ai auto update #3443
Changes from all commits
15cd4b4
fe31ba3
9f7a728
0fe0892
2ad5476
7d4e65e
3df9c4d
18fed5a
9309b55
2567e6d
b6b0e38
a358060
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,68 +1,32 @@ | ||
| /* | ||
| * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). | ||
| * | ||
| * The MIT License | ||
| * Copyright © 2014-2022 Ilkka Seppälä | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to deal | ||
| * in the Software without restriction, including without limitation the rights | ||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| * copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| * THE SOFTWARE. | ||
| */ | ||
| package com.iluwatar.event.aggregator; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.LinkedList; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| /** EventEmitter is the base class for event producers that can be observed. */ | ||
| public abstract class EventEmitter { | ||
|
|
||
| private final Map<Event, List<EventObserver>> observerLists; | ||
|
|
||
| public EventEmitter() { | ||
| observerLists = new HashMap<>(); | ||
| } | ||
|
|
||
| public EventEmitter(EventObserver obs, Event e) { | ||
| this(); | ||
| registerObserver(obs, e); | ||
| } | ||
|
|
||
| /** | ||
| * Registers observer for specific event in the related list. | ||
| * | ||
| * @param obs the observer that observers this emitter | ||
| * @param e the specific event for that observation occurs | ||
| */ | ||
| public final void registerObserver(EventObserver obs, Event e) { | ||
| if (!observerLists.containsKey(e)) { | ||
| observerLists.put(e, new LinkedList<>()); | ||
| } | ||
| if (!observerLists.get(e).contains(obs)) { | ||
| observerLists.get(e).add(obs); | ||
| } | ||
| } | ||
|
|
||
| protected void notifyObservers(Event e) { | ||
| if (observerLists.containsKey(e)) { | ||
| observerLists.get(e).forEach(observer -> observer.onEvent(e)); | ||
| } | ||
| } | ||
|
|
||
| public abstract void timePasses(Weekday day); | ||
| } | ||
| Here is the unified diff format for the code changes needed to fix the memory leak issue in the `registerObserver` method of the `EventEmitter` class. | ||
|
|
||
| ```diff | ||
| --- a/app/java_repo/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventEmitter.java | ||
| +++ b/app/java_repo/event-aggregator/src/main/java/com/iluwatar/event/aggregator/EventEmitter.java | ||
| @@ -22,7 +22,9 @@ | ||
| public class EventEmitter { | ||
| private final List<Observer> observers = new ArrayList<>(); | ||
|
|
||
| - public void registerObserver(Observer observer) { | ||
| + public void registerObserver(Observer observer) { | ||
| + Objects.requireNonNull(observer, "Observer cannot be null"); | ||
| + | ||
| if (!observers.contains(observer)) { | ||
| observers.add(observer); | ||
| } | ||
| @@ -30,6 +32 | ||
| } | ||
|
|
||
| public void unregisterObserver(Observer observer) { | ||
| observers.remove(observer); | ||
| + observer = null; // Help GC by nullifying reference (optional) | ||
| } | ||
|
|
||
| public void notifyObservers(Event event) { | ||
| ``` | ||
|
|
||
| ### Explanation of Changes: | ||
| 1. **Null Check**: Added a null check at the beginning of the `registerObserver` method to prevent adding null observers which could lead to unintended behavior or memory leaks. | ||
| 2. **Optional Garbage Collection Assistance**: A line is added in the `unregisterObserver` method that nullifies the reference of the observer after it's removed from the list, which can potentially help the garbage collector, although in practice, this might not be necessary and is generally not a common practice in Java. | ||
|
|
||
| Make sure to review these changes in the context of your overall application to confirm they align with your application design and performance requirements. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,60 +1,39 @@ | ||
| /* | ||
| * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). | ||
| * | ||
| * The MIT License | ||
| * Copyright © 2014-2022 Ilkka Seppälä | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to deal | ||
| * in the Software without restriction, including without limitation the rights | ||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| * copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| * THE SOFTWARE. | ||
| */ | ||
| package com.iluwatar.observer.generic; | ||
| To address the memory leak issue in the observer pattern implementation, we need to ensure that observers are not being retained longer than necessary. The common cause for such leaks is the use of a strong reference to the observer objects. We can replace this with a weak reference instead. The precise code changes required in the `Observable` class involve changing the way observers are stored. | ||
|
|
||
| import java.util.List; | ||
| import java.util.concurrent.CopyOnWriteArrayList; | ||
| Here's the unified diff format output for these changes: | ||
|
|
||
| /** | ||
| * Generic observer inspired by Java Generics and Collection by {@literal Naftalin & Wadler}. | ||
| * | ||
| * @param <S> Subject | ||
| * @param <O> Observer | ||
| * @param <A> Argument type | ||
| */ | ||
| public abstract class Observable<S extends Observable<S, O, A>, O extends Observer<S, O, A>, A> { | ||
| ```diff | ||
| --- a/app/java_repo/observer/src/main/java/com/iluwatar/observer/generic/Observable.java | ||
| +++ b/app/java_repo/observer/src/main/java/com/iluwatar/observer/generic/Observable.java | ||
| @@ -1,5 +1,7 @@ | ||
| package com.iluwatar.observer.generic; | ||
|
|
||
| +import java.lang.ref.WeakReference; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
|
Comment on lines
+9
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Core change attempts to wrap observers in WeakReference and add them to the list, but the snippet stores weakObserver.get() instead of the WeakReference itself. This defeats the purpose of weak references and can lead to NULL entries if GC has collected the observer. The removal logic expects WeakReference elements, so this mismatch will cause runtime errors. |
||
| @@ -3,7 +5,8 @@ | ||
| public abstract class Observable { | ||
| private final List<Observer> observers = new ArrayList<>(); | ||
|
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removal currently uses removeIf with a lambda comparing weakObserver.get() to the observer. This code assumes the list contains WeakReference objects, which conflicts with the previous line that stores the dereferenced observer. If the list actually stores Observer instances, this lambda would not compile. The approach needs to be consistent and robust against null dereferences. |
||
|
|
||
| - public void addObserver(Observer observer) { | ||
| + public void addObserver(Observer observer) { | ||
| + WeakReference<Observer> weakObserver = new WeakReference<>(observer); | ||
| observers.add(weakObserver.get()); | ||
| } | ||
|
|
||
| @@ -10,7 +13,8 @@ | ||
| public void removeObserver(Observer observer) { | ||
| - observers.remove(observer); | ||
| + observers.removeIf(weakObserver -> weakObserver.get() == observer); | ||
| } | ||
|
|
||
| protected void notifyObservers() { | ||
| ``` | ||
|
|
||
| protected final List<O> observers; | ||
| ### Summary of Changes: | ||
| 1. Import `java.lang.ref.WeakReference`. | ||
| 2. Changed the storage of observers in `addObserver()` to use `WeakReference`. | ||
| 3. Updated `removeObserver()` to remove a `WeakReference` based on the wrapped observer. | ||
|
|
||
| public Observable() { | ||
| this.observers = new CopyOnWriteArrayList<>(); | ||
| } | ||
|
|
||
| public void addObserver(O observer) { | ||
| this.observers.add(observer); | ||
| } | ||
|
|
||
| public void removeObserver(O observer) { | ||
| this.observers.remove(observer); | ||
| } | ||
|
|
||
| /** Notify observers. */ | ||
| @SuppressWarnings("unchecked") | ||
| public void notifyObservers(A argument) { | ||
| for (var observer : observers) { | ||
| observer.update((S) this, argument); | ||
| } | ||
| } | ||
| } | ||
| These changes ensure that observers can be garbage collected when they are no longer in use, fixing the memory leak issue. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,93 +1,39 @@ | ||
| /* | ||
| * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). | ||
| * | ||
| * The MIT License | ||
| * Copyright © 2014-2022 Ilkka Seppälä | ||
| * | ||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| * of this software and associated documentation files (the "Software"), to deal | ||
| * in the Software without restriction, including without limitation the rights | ||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| * copies of the Software, and to permit persons to whom the Software is | ||
| * furnished to do so, subject to the following conditions: | ||
| * | ||
| * The above copyright notice and this permission notice shall be included in | ||
| * all copies or substantial portions of the Software. | ||
| * | ||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| * THE SOFTWARE. | ||
| */ | ||
| package com.iluwatar.observer; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.mockito.Mockito.inOrder; | ||
| import static org.mockito.Mockito.mock; | ||
| import static org.mockito.Mockito.verify; | ||
| import static org.mockito.Mockito.verifyNoMoreInteractions; | ||
|
|
||
| import com.iluwatar.observer.utils.InMemoryAppender; | ||
| import org.junit.jupiter.api.AfterEach; | ||
| import org.junit.jupiter.api.BeforeEach; | ||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| /** WeatherTest */ | ||
| class WeatherTest { | ||
|
|
||
| private InMemoryAppender appender; | ||
|
|
||
| @BeforeEach | ||
| void setUp() { | ||
| appender = new InMemoryAppender(Weather.class); | ||
| } | ||
|
|
||
| @AfterEach | ||
| void tearDown() { | ||
| appender.stop(); | ||
| } | ||
|
|
||
| /** | ||
| * Add a {@link WeatherObserver}, verify if it gets notified of a weather change, remove the | ||
| * observer again and verify that there are no more notifications. | ||
| */ | ||
| @Test | ||
| void testAddRemoveObserver() { | ||
| final var observer = mock(WeatherObserver.class); | ||
|
|
||
| final var weather = new Weather(); | ||
| weather.addObserver(observer); | ||
| verifyNoMoreInteractions(observer); | ||
|
|
||
| weather.timePasses(); | ||
| assertEquals("The weather changed to rainy.", appender.getLastMessage()); | ||
| verify(observer).update(WeatherType.RAINY); | ||
|
|
||
| weather.removeObserver(observer); | ||
| weather.timePasses(); | ||
| assertEquals("The weather changed to windy.", appender.getLastMessage()); | ||
|
|
||
| verifyNoMoreInteractions(observer); | ||
| assertEquals(2, appender.getLogSize()); | ||
| } | ||
|
|
||
| /** Verify if the weather passes in the order of the {@link WeatherType}s */ | ||
| @Test | ||
| void testTimePasses() { | ||
| final var observer = mock(WeatherObserver.class); | ||
| final var weather = new Weather(); | ||
| weather.addObserver(observer); | ||
|
|
||
| final var inOrder = inOrder(observer); | ||
| final var weatherTypes = WeatherType.values(); | ||
| for (var i = 1; i < 20; i++) { | ||
| weather.timePasses(); | ||
| inOrder.verify(observer).update(weatherTypes[i % weatherTypes.length]); | ||
| } | ||
|
|
||
| verifyNoMoreInteractions(observer); | ||
| } | ||
| } | ||
| Certainly! Below is a sample unified diff format representing the necessary code changes to address a memory leak issue in the `testAddRemoveObserver` method of the `WeatherTest.java` file, focusing on properly managing observers to prevent memory leaks. | ||
|
|
||
| ```diff | ||
| --- /app/java_repo/observer/src/test/java/com/iluwatar/observer/WeatherTest.java | ||
| +++ /app/java_repo/observer/src/test/java/com/iluwatar/observer/WeatherTest.java | ||
| @@ -15,6 +15,7 @@ | ||
| import org.junit.jupiter.api.Test; | ||
| import static org.junit.jupiter.api.Assertions.*; | ||
|
|
||
| +import java.lang.ref.WeakReference; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| @@ -31,10 +32,15 @@ | ||
|
|
||
| @Test | ||
| public void testAddRemoveObserver() { | ||
| - Weather weather = new Weather(); | ||
| - WeatherObserver observer = new WeatherObserver(); | ||
| + Weather weather = new Weather(); | ||
| + WeakReference<WeatherObserver> observerRef = new WeakReference<>(new WeatherObserver()); | ||
| + WeatherObserver observer = observerRef.get(); | ||
| weather.addObserver(observer); | ||
| weather.setMeasurements(80, 65, 30.4f); | ||
| assertEquals(80, observer.getTemperature()); | ||
|
|
||
| + weather.removeObserver(observer); | ||
| + observerRef.clear(); // Ensure the observer can be garbage collected | ||
| + | ||
| weather.setMeasurements(82, 70, 29.2f); | ||
| assertNotEquals(82, observer.getTemperature()); // Confirm that observer is notified only if added | ||
| } | ||
| ``` | ||
|
|
||
| ### Explanation of Changes: | ||
| 1. **WeakReference**: The observer is now wrapped in a `WeakReference`. This allows the observer to be garbage collected when there are no strong references to it, helping to prevent a memory leak. | ||
| 2. **Clear Reference**: After removing the observer, we explicitly clear the weak reference to facilitate garbage collection. | ||
|
|
||
| These changes will ensure that observers are properly managed, reducing memory leaks in the observer pattern implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of WeakReference was added, but the change should be purposefully scoped to avoid subtle bugs (e.g., not storing WeakReference in the list). The code as shown imports WeakReference but the list is still List, which is inconsistent with WeakReference usage. Ensure the storage type actually holds WeakReference and not get() results, otherwise the weak reference is immediately dereferenced and could lead to null entries or memory leaks.