On Mon, 25 Apr 2022 06:07:00 GMT, Xue-Lei Andrew Fan <xue...@openjdk.org> wrote:
>> Please review the update to remove finalizer method in the >> java.security.jgss module. It is one of the efforts to clean up the use of >> finalizer method in JDK. > > Xue-Lei Andrew Fan has updated the pull request with a new target base due to > a merge or a rebase. The pull request now contains 10 commits: > > - Merge and resovle merge conflict > - change the calling order in dispose() > - More code cleanup > - re-org the code per feedback > - Update to set context method > - add test cases > - Merge > - Update copyright year > - the object reference issue for Cleaner > - 8284490: Remove finalizer method in java.security.jgss Can you try out this test? diff --git a/test/jdk/sun/security/krb5/auto/Cleaners.java b/test/jdk/sun/security/krb5/auto/Cleaners.java new file mode 100644 index 00000000000..0eac7c21ee6 --- /dev/null +++ b/test/jdk/sun/security/krb5/auto/Cleaners.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8284490 + * @summary Remove finalizer method in java.security.jgss + * @library /test/lib + * @compile -XDignore.symbol.file Cleaners.java + * @run main/othervm Cleaners launcher + */ + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermission; +import java.util.Arrays; +import java.util.Set; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; +import jdk.test.lib.process.Proc; +import org.ietf.jgss.Oid; +import sun.security.krb5.Config; + +public class Cleaners { + + private static final String CONF = "krb5.conf"; + private static final String KTAB_S = "server.ktab"; + private static final String KTAB_B = "backend.ktab"; + + private static final String HOST = "localhost"; + private static final String SERVER = "server/" + HOST; + private static final String BACKEND = "backend/" + HOST; + private static final String USER = "user"; + private static final char[] PASS = "password".toCharArray(); + private static final String REALM = "REALM"; + + private static final byte[] MSG = "12345678".repeat(128) + .getBytes(StandardCharsets.UTF_8); + + public static void main(String[] args) throws Exception { + + Oid oid = new Oid("1.2.840.113554.1.2.2"); + byte[] token, msg; + + switch (args[0]) { + case "launcher" -> { + KDC kdc = KDC.create(REALM, HOST, 0, true); + kdc.addPrincipal(USER, PASS); + kdc.addPrincipalRandKey("krbtgt/" + REALM); + kdc.addPrincipalRandKey(SERVER); + kdc.addPrincipalRandKey(BACKEND); + + // Native lib might do some name lookup + KDC.saveConfig(CONF, kdc, + "dns_lookup_kdc = no", + "ticket_lifetime = 1h", + "dns_lookup_realm = no", + "dns_canonicalize_hostname = false", + "forwardable = true"); + System.setProperty("java.security.krb5.conf", CONF); + Config.refresh(); + + // Create kaytab and ccache files for native clients + kdc.writeKtab(KTAB_S, false, SERVER); + kdc.writeKtab(KTAB_B, false, BACKEND); + kdc.kinit(USER, "ccache"); + if (!Platform.isWindows()) { + Files.setPosixFilePermissions(Paths.get("ccache"), + Set.of(PosixFilePermission.OWNER_READ, + PosixFilePermission.OWNER_WRITE)); + } + Proc pc = proc("client") + .env("KRB5CCNAME", "FILE:ccache") + .env("KRB5_KTNAME", "none") // Do not try system ktab if ccache fails + .start(); + Proc ps = proc("server") + .env("KRB5_KTNAME", KTAB_S) + .start(); + Proc pb = proc("backend") + .env("KRB5_KTNAME", KTAB_B) + .start(); + + // Client and server + ps.println(pc.readData()); // AP-REQ + pc.println(ps.readData()); // AP-REP, mutual auth + ps.println(pc.readData()); // wrap msg + ps.println(pc.readData()); // mic msg + + + // Server and backend + pb.println(ps.readData()); // AP-REQ + ps.println(pb.readData()); // wrap msg + ps.println(pb.readData()); // mic msg + ensureCleanersCalled(pc); + ensureCleanersCalled(ps); + ensureCleanersCalled(pb); + } + case "client" -> { + Context c = Context.fromThinAir(); + c.startAsClient(SERVER, oid); + c.x().requestCredDeleg(true); + c.x().requestMutualAuth(true); + Proc.binOut(c.take(new byte[0])); // AP-REQ + c.take(Proc.binIn()); // AP-REP + Proc.binOut(c.wrap(MSG, true)); + Proc.binOut(c.getMic(MSG)); + } + case "server" -> { + Context s = Context.fromThinAir(); + s.startAsServer(oid); + token = Proc.binIn(); // AP-REQ + Proc.binOut(s.take(token)); // AP-REP + msg = s.unwrap(Proc.binIn(), true); + Asserts.assertTrue(Arrays.equals(msg, MSG)); + s.verifyMic(Proc.binIn(), msg); + Context s2 = s.delegated(); + s2.startAsClient(BACKEND, oid); + s2.x().requestMutualAuth(false); + Proc.binOut(s2.take(new byte[0])); // AP-REQ + msg = s2.unwrap(Proc.binIn(), true); + Asserts.assertTrue(Arrays.equals(msg, MSG)); + s2.verifyMic(Proc.binIn(), msg); + } + case "backend" -> { + Context b = Context.fromThinAir(); + b.startAsServer(oid); + token = b.take(Proc.binIn()); // AP-REQ + Asserts.assertTrue(token == null); + Proc.binOut(b.wrap(MSG, true)); + Proc.binOut(b.getMic(MSG)); + } + } + System.out.println("Prepare for GC"); + for (int i = 0; i < 10; i++) { + System.gc(); + Thread.sleep(100); + } + } + + private static void ensureCleanersCalled(Proc p) throws Exception { + p.output() + .shouldHaveExitValue(0) + .stdoutShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_deleteContext") + .stdoutShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_releaseName") + .stdoutShouldMatch("Prepare for GC(.|\\n)*GSSLibStub_releaseCred"); + } + + private static Proc proc(String type) throws Exception { + return Proc.create("Cleaners") + .args(type) + .debug(type) + .env("KRB5_CONFIG", CONF) + .env("KRB5_TRACE", Platform.isWindows() ? "CON" : "/dev/stderr") + .prop("sun.security.jgss.native", "true") + .prop("javax.security.auth.useSubjectCredsOnly", "false") + .prop("sun.security.nativegss.debug", "true"); + } +} diff --git a/test/lib/jdk/test/lib/process/Proc.java b/test/lib/jdk/test/lib/process/Proc.java index 3541f34144f..574e5761d03 100644 --- a/test/lib/jdk/test/lib/process/Proc.java +++ b/test/lib/jdk/test/lib/process/Proc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,6 +123,7 @@ public class Proc { private String debug; // debug flag, controller will show data // transfer between procs. If debug is set, // it MUST be different between Procs. + private final StringBuilder stdout = new StringBuilder(); final private static String PREFIX = "PROCISFUN:"; @@ -358,6 +359,9 @@ public class Proc { // Reads a line from stdout of proc public String readLine() throws IOException { String s = br.readLine(); + if (s != null) { + stdout.append(s).append('\n'); + } if (debug != null) { System.out.println("PROC: " + debug + " readline: " + (s == null ? "<EOF>" : s)); @@ -402,6 +406,16 @@ public class Proc { } return p.waitFor(); } + + // Returns an OutputAnalyzer + public OutputAnalyzer output() throws Exception { + int exitCode = waitFor(); + Path stderr = Path.of(getId("stderr")); + return new OutputAnalyzer(stdout.toString(), + Files.exists(stderr) ? Files.readString(stderr) : "", + exitCode); + } + // Wait for process end with expected exit code public void waitFor(int expected) throws Exception { if (p.waitFor() != expected) { ------------- PR: https://git.openjdk.java.net/jdk/pull/8136