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