提交 7787f593 编写于 作者: A aefimov

Merge

......@@ -1189,6 +1189,7 @@ e4f39d283b55faf6074308797615298bd1a45a66 jdk8u181-b11
464ed8cea5d6cdbfacc9be7035297af88f57f708 jdk8u181-b12
eed8e846c982d7474dd07fc873ba02f83ad1f847 jdk8u181-b13
21a3fffc43418f4d75c2091bf03478330b8a9a98 jdk8u191-b01
2bf8498a25ec87c92584a6542f8724644c8c5706 jdk8u201-b00
5aa3d728164a674d08ad847811be6bdd853e9bf8 jdk8u191-b02
dd79b482625361458b2b34e7d669ee982eee06a4 jdk8u191-b03
541c205d7fd15ab840f48aaeeaea3f63209d1687 jdk8u191-b04
......@@ -1219,6 +1220,16 @@ b675533489ae1dc55469885471c9a29eca584d38 jdk8u192-b10
8df818c645d6081a387cf4fe9b9c14c0b5b639b1 jdk8u192-b11
1f822ff877d1a250165d5d2d52faf6957f8fcd00 jdk8u192-b12
e0e4c3a86ef0e4daf4fe96bd058045a2b13ebf84 jdk8u192-b26
f7bd3ef62b03503c2abd2c877103fce4c41752ec jdk8u181-b31
a2be8e761961b9aea1641593f2638406c8052bff jdk8u181-b32
9d9f4c81eb3df5991f4409429a8eed5da385e138 jdk8u181-b33
2ac6a4ff7b3c9c45bda2a449523f7f1babffd857 jdk8u181-b34
f3eb9719e6961890add8af56c43a3273bedd3510 jdk8u181-b35
5418d85b93ea93af1b75a700501cab9e53e282c5 jdk8u181-b36
310a8a03be9363e47cc0856e43661cf71b516101 jdk8u181-b37
cec91c1510a4f6b54f454f8a18c2ce19e1ef4002 jdk8u201-b01
242132d678006ccd4139c33c1a188f09a09683c6 jdk8u201-b02
68ee3b18354df0572de37bc04c3a7a8046d5a654 jdk8u201-b03
79b4c0a88c00226dcd14496652adf84d53b5cb9c jdk8u202-b01
9ce27f0a4683a2083d3aed59a40d6a3ccfc8e397 jdk8u202-b02
c0836eee40e5cfc7b3eebbb7a53bfcd98bc66278 jdk8u202-b03
......@@ -4210,9 +4210,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
this_klass(), &all_mirandas, CHECK_(nullHandle));
}
// Update the loader_data graph.
record_defined_class_dependencies(this_klass, CHECK_NULL);
ClassLoadingService::notify_class_loaded(InstanceKlass::cast(this_klass()),
false /* not shared class */);
......@@ -4498,30 +4495,6 @@ void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) {
}
}
// Attach super classes and interface classes to class loader data
void ClassFileParser::record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS) {
ClassLoaderData * defining_loader_data = defined_klass->class_loader_data();
if (defining_loader_data->is_the_null_class_loader_data()) {
// Dependencies to null class loader data are implicit.
return;
} else {
// add super class dependency
Klass* super = defined_klass->super();
if (super != NULL) {
defining_loader_data->record_dependency(super, CHECK);
}
// add super interface dependencies
Array<Klass*>* local_interfaces = defined_klass->local_interfaces();
if (local_interfaces != NULL) {
int length = local_interfaces->length();
for (int i = 0; i < length; i++) {
defining_loader_data->record_dependency(local_interfaces->at(i), CHECK);
}
}
}
}
// utility methods for appending an array with check for duplicates
void append_interfaces(GrowableArray<Klass*>* result, Array<Klass*>* ifs) {
......
/*
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2018, 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
......@@ -159,33 +159,9 @@ void Dictionary::do_unloading() {
if (!is_strongly_reachable(loader_data, e)) {
// Entry was not visited in phase1 (negated test from phase1)
assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader");
ClassLoaderData* k_def_class_loader_data = ik->class_loader_data();
// Do we need to delete this system dictionary entry?
bool purge_entry = false;
// Do we need to delete this system dictionary entry?
if (loader_data->is_unloading()) {
// If the loader is not live this entry should always be
// removed (will never be looked up again).
purge_entry = true;
} else {
// The loader in this entry is alive. If the klass is dead,
// (determined by checking the defining class loader)
// the loader must be an initiating loader (rather than the
// defining loader). Remove this entry.
if (k_def_class_loader_data->is_unloading()) {
// If we get here, the class_loader_data must not be the defining
// loader, it must be an initiating one.
assert(k_def_class_loader_data != loader_data,
"cannot have live defining loader and unreachable klass");
// Loader is live, but class and its defining loader are dead.
// Remove the entry. The class is going away.
purge_entry = true;
}
}
if (purge_entry) {
*p = probe->next();
if (probe == _current_class_entry) {
_current_class_entry = NULL;
......
......@@ -816,7 +816,16 @@ Klass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
check_constraints(d_index, d_hash, k, class_loader, false, THREAD);
// Need to check for a PENDING_EXCEPTION again; check_constraints
// can throw and doesn't use the CHECK macro.
// can throw but we may have to remove entry from the placeholder table below.
if (!HAS_PENDING_EXCEPTION) {
// Record dependency for non-parent delegation.
// This recording keeps the defining class loader of the klass (k) found
// from being unloaded while the initiating class loader is loaded
// even if the reference to the defining class loader is dropped
// before references to the initiating class loader.
loader_data->record_dependency(k(), THREAD);
}
if (!HAS_PENDING_EXCEPTION) {
{ // Grabbing the Compile_lock prevents systemDictionary updates
// during compilations.
......
......@@ -63,7 +63,6 @@ bool VerificationType::is_reference_assignable_from(
name(), Handle(THREAD, klass->class_loader()),
Handle(THREAD, klass->protection_domain()), true, CHECK_false);
KlassHandle this_class(THREAD, obj);
klass->class_loader_data()->record_dependency(obj, CHECK_false);
if (this_class->is_interface() && (!from_field_is_protected ||
from.name() != vmSymbols::java_lang_Object())) {
......@@ -75,7 +74,6 @@ bool VerificationType::is_reference_assignable_from(
Klass* from_class = SystemDictionary::resolve_or_fail(
from.name(), Handle(THREAD, klass->class_loader()),
Handle(THREAD, klass->protection_domain()), true, CHECK_false);
klass->class_loader_data()->record_dependency(from_class, CHECK_false);
bool result = InstanceKlass::cast(from_class)->is_subclass_of(this_class());
if (result && DumpSharedSpaces) {
if (klass()->is_subclass_of(from_class) && klass()->is_subclass_of(this_class())) {
......
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2018, 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
......@@ -1949,11 +1949,9 @@ Klass* ClassVerifier::load_class(Symbol* name, TRAPS) {
oop loader = current_class()->class_loader();
oop protection_domain = current_class()->protection_domain();
Klass* kls = SystemDictionary::resolve_or_fail(
return SystemDictionary::resolve_or_fail(
name, Handle(THREAD, loader), Handle(THREAD, protection_domain),
true, CHECK_NULL);
current_class()->class_loader_data()->record_dependency(kls, CHECK_NULL);
return kls;
}
bool ClassVerifier::is_protected_access(instanceKlassHandle this_class,
......
......@@ -339,8 +339,6 @@ Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS
// Only updated constant pool - if it is resolved.
do_resolve = this_oop->tag_at(which).is_unresolved_klass();
if (do_resolve) {
ClassLoaderData* this_key = this_oop->pool_holder()->class_loader_data();
this_key->record_dependency(k(), CHECK_NULL); // Can throw OOM
this_oop->klass_at_put(which, k());
}
}
......
/*
* Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2018, 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
......@@ -209,12 +209,22 @@ void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_co
if (byte_no == 1) {
assert(invoke_code != Bytecodes::_invokevirtual &&
invoke_code != Bytecodes::_invokeinterface, "");
bool do_resolve = true;
// Don't mark invokespecial to method as resolved if sender is an interface. The receiver
// has to be checked that it is a subclass of the current class every time this bytecode
// is executed.
if (invoke_code != Bytecodes::_invokespecial || !sender_is_interface ||
method->name() == vmSymbols::object_initializer_name()) {
set_bytecode_1(invoke_code);
if (invoke_code == Bytecodes::_invokespecial && sender_is_interface &&
method->name() != vmSymbols::object_initializer_name()) {
do_resolve = false;
}
// Don't mark invokestatic to method as resolved if the holder class has not yet completed
// initialization. An invokestatic must only proceed if the class is initialized, but if
// we resolve it before then that class initialization check is skipped.
if (invoke_code == Bytecodes::_invokestatic && !method->method_holder()->is_initialized()) {
do_resolve = false;
}
if (do_resolve) {
set_bytecode_1(invoke_code);
}
} else if (byte_no == 2) {
if (change_to_virtual) {
......
......@@ -991,12 +991,6 @@ JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name,
Handle h_prot (THREAD, protection_domain);
jclass result = find_class_from_class_loader(env, h_name, init, h_loader,
h_prot, true, thread);
if (result != NULL) {
oop mirror = JNIHandles::resolve_non_null(result);
Klass* to_class = java_lang_Class::as_Klass(mirror);
ClassLoaderData* cld = ClassLoaderData::class_loader_data(h_loader());
cld->record_dependency(to_class, CHECK_NULL);
}
if (TraceClassResolution && result != NULL) {
// this function is generally only used for class loading during verification.
......
......@@ -1232,6 +1232,14 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread,
}
#endif
// Do not patch call site for static call when the class is not
// fully initialized.
if (invoke_code == Bytecodes::_invokestatic &&
!callee_method->method_holder()->is_initialized()) {
assert(callee_method->method_holder()->is_linked(), "must be");
return callee_method;
}
// JSR 292 key invariant:
// If the resolved method is a MethodHandle invoke target, the call
// site must be a MethodHandle call site, because the lambda form might tail-call
......
/*
* Copyright (c) 2018, 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 ConstantPoolDependsTest
* @bug 8210094
* @summary Create ClassLoader dependency from initiating loader to class loader through constant pool reference
* @modules java.base/jdk.internal.misc
* java.compiler
* @library /testlibrary /testlibrary/whitebox /runtime/testlibrary
* @build sun.hotspot.WhiteBox
* @compile p2/c2.java MyDiffClassLoader.java
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ConstantPoolDependsTest
*/
import sun.hotspot.WhiteBox;
public class ConstantPoolDependsTest {
public static WhiteBox wb = WhiteBox.getWhiteBox();
public static final String MY_TEST = "ConstantPoolDependsTest$c1c";
public static class c1c {
private void test() throws Exception {
// ConstantPool.klass_at_impl loads through constant pool and creates dependency
p2.c2 c2_obj = new p2.c2();
c2_obj.method2();
}
public c1c () throws Exception {
test();
ClassUnloadCommon.triggerUnloading(); // should not unload anything
test();
ClassUnloadCommon.triggerUnloading(); // should not unload anything
}
}
static void test() throws Throwable {
// now use the same loader to load class MyTest
Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
try {
// Call MyTest to load p2.c2 twice and call p2.c2.method2
MyTest_class.newInstance();
} catch (Exception e) {
throw new RuntimeException("Test FAILED if NoSuchMethodException is thrown");
}
ClassUnloadCommon.triggerUnloading(); // should not unload anything
ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
// Unless MyTest_class is referenced here, the compiler can unload it.
System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
}
public static void main(String args[]) throws Throwable {
test();
ClassUnloadCommon.triggerUnloading(); // should unload
System.gc();
System.out.println("Should unload p2.c2 just now");
ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
}
}
/*
* Copyright (c) 2018, 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 DictionaryDependsTest
* @bug 8210094
* @summary Create ClassLoader dependency from initiating loader to class loader through reflection
* @modules java.base/jdk.internal.misc
* java.compiler
* @library /testlibrary /testlibrary/whitebox /runtime/testlibrary
* @build sun.hotspot.WhiteBox
* @compile p2/c2.java MyDiffClassLoader.java
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DictionaryDependsTest
*/
import sun.hotspot.WhiteBox;
import java.lang.reflect.Method;
public class DictionaryDependsTest {
public static WhiteBox wb = WhiteBox.getWhiteBox();
public static final String MY_TEST = "DictionaryDependsTest$c1r";
static public class c1r {
private void test() throws Exception {
// forName loads through reflection and doesn't create dependency
Class<?> x = Class.forName("p2.c2", true, c1r.class.getClassLoader());
Method m = x.getMethod("method2");
java.lang.Object t = x.newInstance();
m.invoke(t);
}
public c1r () throws Exception {
test();
ClassUnloadCommon.triggerUnloading(); // should unload p2.c2
test();
ClassUnloadCommon.triggerUnloading(); // should unload p2.c2
}
}
public void test() throws Throwable {
// now use the same loader to load class MyTest
Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
try {
// Call MyTest to load p2.c2 twice and call p2.c2.method2
MyTest_class.newInstance();
} catch (Exception e) {
System.out.println("Not expected NSME");
throw new RuntimeException("Not expecting NSME");
}
ClassUnloadCommon.triggerUnloading(); // should not unload anything
ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
// Unless MyTest_class is referenced here, the compiler can unload it.
System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
}
public static void main(String args[]) throws Throwable {
DictionaryDependsTest d = new DictionaryDependsTest();
d.test();
ClassUnloadCommon.triggerUnloading(); // should not unload anything
System.out.println("Should unload MyTest and p2.c2 just now");
ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
}
}
/*
* Copyright (c) 2018, 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.
*/
import java.io.*;
import com.oracle.java.testlibrary.InMemoryJavaCompiler;
public class MyDiffClassLoader extends ClassLoader {
public String loaderName;
public static boolean switchClassData = false;
MyDiffClassLoader(String name) {
this.loaderName = name;
}
public Class loadClass(String name) throws ClassNotFoundException {
if (!name.contains("c1r") &&
!name.contains("c1c") &&
!name.contains("c1s") &&
!name.equals("p2.c2")) {
return super.loadClass(name);
}
// new loader loads p2.c2
if (name.equals("p2.c2") && !loaderName.equals("C2Loader")) {
Class<?> c = new MyDiffClassLoader("C2Loader").loadClass(name);
switchClassData = true;
return c;
}
byte[] data = switchClassData ? getNewClassData(name) : getClassData(name);
System.out.println("name is " + name);
return defineClass(name, data, 0, data.length);
}
byte[] getClassData(String name) {
try {
String TempName = name.replaceAll("\\.", "/");
String currentDir = System.getProperty("test.classes");
String filename = currentDir + File.separator + TempName + ".class";
FileInputStream fis = new FileInputStream(filename);
byte[] b = new byte[5000];
int cnt = fis.read(b, 0, 5000);
byte[] c = new byte[cnt];
for (int i=0; i<cnt; i++) c[i] = b[i];
return c;
} catch (IOException e) {
return null;
}
}
// Return p2.c2 with everything removed
byte[] getNewClassData(String name) {
return InMemoryJavaCompiler.compile("p2.c2", "package p2; public class c2 { }");
}
}
/*
* Copyright (c) 2018, 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 SuperDependsTest
* @bug 8210094
* @summary Create ClassLoader dependency from initiating loader to class loader through subclassing
* @modules java.base/jdk.internal.misc
* java.compiler
* @library /testlibrary /testlibrary/whitebox /runtime/testlibrary
* @build sun.hotspot.WhiteBox
* @compile p2/c2.java MyDiffClassLoader.java
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:. -Xmn8m -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SuperDependsTest
*/
import sun.hotspot.WhiteBox;
import p2.*;
public class SuperDependsTest {
public static WhiteBox wb = WhiteBox.getWhiteBox();
public static final String MY_TEST = "SuperDependsTest$c1s";
// p2.c2 loads through super class and creates dependency
public static class c1s extends p2.c2 {
private void test() throws Exception {
method2();
}
public c1s () throws Exception {
test();
ClassUnloadCommon.triggerUnloading(); // should not unload anything
test();
}
}
public void test() throws Throwable {
// now use the same loader to load class MyTest
Class MyTest_class = new MyDiffClassLoader(MY_TEST).loadClass(MY_TEST);
// Call MyTest to load p2.c2 twice and call p2.c2.method2
MyTest_class.newInstance();
ClassUnloadCommon.triggerUnloading(); // should not unload anything
ClassUnloadCommon.failIf(!wb.isClassAlive(MY_TEST), "should not be unloaded");
ClassUnloadCommon.failIf(!wb.isClassAlive("p2.c2"), "should not be unloaded");
// Unless MyTest_class is referenced here, the compiler can unload it.
System.out.println("Should not unload anything before here because " + MyTest_class + " is still alive.");
}
public static void main(String args[]) throws Throwable {
SuperDependsTest d = new SuperDependsTest();
d.test();
ClassUnloadCommon.triggerUnloading(); // should not unload anything
System.out.println("Should unload MyTest and p2.c2 just now");
ClassUnloadCommon.failIf(wb.isClassAlive(MY_TEST), "should be unloaded");
ClassUnloadCommon.failIf(wb.isClassAlive("p2.c2"), "should be unloaded");
}
}
/*
* Copyright (c) 2018, 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.
*/
package p2;
public class c2 {
int i;
public void method2() { i = 5; System.out.println("c2 method2 called"); }
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册