1620ba73aSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3620ba73aSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4620ba73aSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5620ba73aSAndrew Rist  * distributed with this work for additional information
6620ba73aSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7620ba73aSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8620ba73aSAndrew Rist  * "License"); you may not use this file except in compliance
9620ba73aSAndrew Rist  * with the License.  You may obtain a copy of the License at
10620ba73aSAndrew Rist  *
11620ba73aSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12620ba73aSAndrew Rist  *
13620ba73aSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14620ba73aSAndrew Rist  * software distributed under the License is distributed on an
15620ba73aSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16620ba73aSAndrew Rist  * KIND, either express or implied.  See the License for the
17620ba73aSAndrew Rist  * specific language governing permissions and limitations
18620ba73aSAndrew Rist  * under the License.
19620ba73aSAndrew Rist  *
20620ba73aSAndrew Rist  *************************************************************/
21620ba73aSAndrew Rist 
22620ba73aSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir package com.sun.star.lib.uno.bridges.javaremote;
25cdf0e10cSrcweir 
26cdf0e10cSrcweir import com.sun.star.bridge.XInstanceProvider;
27cdf0e10cSrcweir import com.sun.star.lib.TestBed;
28cdf0e10cSrcweir import com.sun.star.lib.uno.typeinfo.MethodTypeInfo;
29cdf0e10cSrcweir import com.sun.star.lib.uno.typeinfo.TypeInfo;
30cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime;
31cdf0e10cSrcweir import com.sun.star.uno.XComponentContext;
32cdf0e10cSrcweir import com.sun.star.uno.XInterface;
33*9e878ba5SDamjan Jovanovic 
34*9e878ba5SDamjan Jovanovic import org.junit.Test;
35*9e878ba5SDamjan Jovanovic import static org.junit.Assert.*;
36*9e878ba5SDamjan Jovanovic 
37cdf0e10cSrcweir 
38cdf0e10cSrcweir /**
39cdf0e10cSrcweir  * Test case for bug #108825#.
40cdf0e10cSrcweir  *
41cdf0e10cSrcweir  * <p>Bug #108825# "Java UNO Remote Bridge: Mapped-out Objects Not Held" shows
42cdf0e10cSrcweir  * that local objects that are mapped out via a remote bridge, but not held
43cdf0e10cSrcweir  * locally, might be garbage collected while there are still remote references
44cdf0e10cSrcweir  * to them.  This test is not guaranteed to always work reliably, see comment in
45cdf0e10cSrcweir  * the code.</p>
46cdf0e10cSrcweir  */
47*9e878ba5SDamjan Jovanovic public final class Bug108825_Test  {
48*9e878ba5SDamjan Jovanovic     @Test
test()49cdf0e10cSrcweir     public void test() throws Exception {
50cdf0e10cSrcweir         TestBed t = new TestBed();
51*9e878ba5SDamjan Jovanovic         assertTrue("test", t.execute(new Provider(t), true, Client.class, 0));
52cdf0e10cSrcweir     }
53cdf0e10cSrcweir 
54cdf0e10cSrcweir     public static final class Client extends TestBed.Client {
main(String[] args)55cdf0e10cSrcweir         public static void main(String[] args) {
56cdf0e10cSrcweir             new Client().execute();
57cdf0e10cSrcweir         }
58cdf0e10cSrcweir 
run(XComponentContext context)59cdf0e10cSrcweir         protected boolean run(XComponentContext context) throws Throwable {
60cdf0e10cSrcweir             XTest test = UnoRuntime.queryInterface(
61cdf0e10cSrcweir                 XTest.class, getBridge(context).getInstance("Test"));
62cdf0e10cSrcweir             // Send the XObject that is held on the server side amidst two
63cdf0e10cSrcweir             // dummies that are not held on the server side; then wait for the
64cdf0e10cSrcweir             // dummies to be garbage collected, hoping that the XObject, if it
65cdf0e10cSrcweir             // is erroneously not held on the client side, will be garbage
66cdf0e10cSrcweir             // collected, too.  Obviously, this is not guaranteed to always work
67cdf0e10cSrcweir             // (the VM might chose not to garbage collect the dummies, hanging
68cdf0e10cSrcweir             // the test forever; or the VM might chose to garbage collect the
69cdf0e10cSrcweir             // dummies but not the XObject, making the test pass erroneously).
70cdf0e10cSrcweir             test.offer(new Dummy(), new XObject() { public void call() {} },
71cdf0e10cSrcweir                        new Dummy());
72cdf0e10cSrcweir             System.out.println("Client waiting for garbage collection...");
73cdf0e10cSrcweir             for (;;) {
74cdf0e10cSrcweir                 synchronized (lock) {
75cdf0e10cSrcweir                     if (finalizedCount == 2) {
76cdf0e10cSrcweir                         break;
77cdf0e10cSrcweir                     }
78cdf0e10cSrcweir                 }
79cdf0e10cSrcweir                 test.remoteGc();
80cdf0e10cSrcweir                 gc();
81cdf0e10cSrcweir             }
82cdf0e10cSrcweir             System.out.println("Client garbage collection done.");
83cdf0e10cSrcweir             test.notification();
84cdf0e10cSrcweir             return true;
85cdf0e10cSrcweir         }
86cdf0e10cSrcweir 
87cdf0e10cSrcweir         private final class Dummy implements XDummy {
finalize()88cdf0e10cSrcweir             protected void finalize() {
89cdf0e10cSrcweir                 synchronized (lock) {
90cdf0e10cSrcweir                     ++finalizedCount;
91cdf0e10cSrcweir                 }
92cdf0e10cSrcweir             }
93cdf0e10cSrcweir         }
94cdf0e10cSrcweir 
95cdf0e10cSrcweir         private final Object lock = new Object();
96cdf0e10cSrcweir         private int finalizedCount = 0;
97cdf0e10cSrcweir     }
98cdf0e10cSrcweir 
99cdf0e10cSrcweir     // Make it as likely as possible that the VM reclaims all garbage:
gc()100cdf0e10cSrcweir     private static void gc() {
101cdf0e10cSrcweir         System.gc();
102cdf0e10cSrcweir         System.runFinalization();
103cdf0e10cSrcweir         byte[] garbage = new byte[1024 * 1024];
104cdf0e10cSrcweir     }
105cdf0e10cSrcweir 
106cdf0e10cSrcweir     private static final class Provider implements XInstanceProvider {
Provider(TestBed testBed)107cdf0e10cSrcweir         public Provider(TestBed testBed) {
108cdf0e10cSrcweir             this.testBed = testBed;
109cdf0e10cSrcweir         }
110cdf0e10cSrcweir 
getInstance(String instanceName)111cdf0e10cSrcweir         public Object getInstance(String instanceName) {
112cdf0e10cSrcweir             return new XTest() {
113cdf0e10cSrcweir                     public void offer(XDummy dummy1, XObject obj, XDummy dummy2)
114cdf0e10cSrcweir                     {
115cdf0e10cSrcweir                         this.obj = obj;
116cdf0e10cSrcweir                     }
117cdf0e10cSrcweir 
118cdf0e10cSrcweir                     public void remoteGc() {
119cdf0e10cSrcweir                         gc();
120cdf0e10cSrcweir                     }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir                     public void notification() {
123cdf0e10cSrcweir                         obj.call();
124cdf0e10cSrcweir                         testBed.serverDone(true);
125cdf0e10cSrcweir                     }
126cdf0e10cSrcweir 
127cdf0e10cSrcweir                     private XObject obj;
128cdf0e10cSrcweir                 };
129cdf0e10cSrcweir         }
130cdf0e10cSrcweir 
131cdf0e10cSrcweir         private final TestBed testBed;
132cdf0e10cSrcweir     }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir     public interface XDummy extends XInterface {
135cdf0e10cSrcweir         TypeInfo[] UNOTYPEINFO = null;
136cdf0e10cSrcweir     }
137cdf0e10cSrcweir 
138cdf0e10cSrcweir     public interface XObject extends XInterface {
139cdf0e10cSrcweir         void call();
140cdf0e10cSrcweir 
141cdf0e10cSrcweir         TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("call", 0, 0) };
142cdf0e10cSrcweir     }
143cdf0e10cSrcweir 
144cdf0e10cSrcweir     public interface XTest extends XInterface {
145cdf0e10cSrcweir         void offer(XDummy dummy1, XObject obj, XDummy dummy2);
146cdf0e10cSrcweir 
147cdf0e10cSrcweir         void remoteGc();
148cdf0e10cSrcweir 
149cdf0e10cSrcweir         void notification();
150cdf0e10cSrcweir 
151cdf0e10cSrcweir         TypeInfo[] UNOTYPEINFO = { new MethodTypeInfo("offer", 0, 0),
152cdf0e10cSrcweir                                    new MethodTypeInfo("remoteGc", 1, 0),
153cdf0e10cSrcweir                                    new MethodTypeInfo("notification", 2, 0) };
154cdf0e10cSrcweir     }
155cdf0e10cSrcweir }
156