/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
System.loadLibrary(args[0]);
if (!checkAppImageLoaded()) {
System.out.println("AppImage not loaded.");
}
expectNotPreInit(Day.class);
expectNotPreInit(ClInit.class); // should pass
expectNotPreInit(A.class); // should pass
expectNotPreInit(B.class); // should fail
expectNotPreInit(C.class); // should fail
expectNotPreInit(G.class); // should fail
expectNotPreInit(Gs.class); // should fail
expectNotPreInit(Gss.class); // should fail
expectNotPreInit(Add.class);
expectNotPreInit(Mul.class);
expectNotPreInit(ObjectRef.class);
A x = new A();
System.out.println("A.a: " + A.a);
B y = new B();
C z = new C();
System.out.println("A.a: " + A.a);
System.out.println("B.b: " + B.b);
System.out.println("C.c: " + C.c);
ClInit c = new ClInit();
int aa = c.a;
System.out.println("X: " + c.getX());
System.out.println("Y: " + c.getY());
System.out.println("str: " + c.str);
System.out.println("ooo: " + c.ooo);
System.out.println("Z: " + c.getZ());
System.out.println("A: " + c.getA());
System.out.println("AA: " + aa);
if (c.a != 101) {
System.out.println("a != 101");
}
return;
}
static void expectPreInit(Class<?> klass) {
if (checkInitialized(klass) == false) {
System.out.println(klass.getName() + " should be initialized!");
}
}
static void expectNotPreInit(Class<?> klass) {
if (checkInitialized(klass) == true) {
System.out.println(klass.getName() + " should not be initialized!");
}
}
public static native boolean checkAppImageLoaded();
public static native boolean checkAppImageContains(Class<?> klass);
public static native boolean checkInitialized(Class<?> klass);
}
enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
class ClInit {
static String ooo = "OoooooO";
static String str;
static int z;
static int x, y;
public static volatile int a = 100;
static {
StringBuilder sb = new StringBuilder();
sb.append("Hello ");
sb.append("World!");
str = sb.toString();
z = 0xFF;
z += 0xFF00;
z += 0xAA0000;
for(int i = 0; i < 100; i++) {
x += i;
}
y = x;
for(int i = 0; i < 40; i++) {
y += i;
}
}
int getX() {
return x;
}
int getZ() {
return z;
}
int getY() {
return y;
}
int getA() {
return a;
}
}
class A {
public static int a = 2;
static {
a = 5; // self-updating, pass
}
}
class B {
public static int b;
static {
A.a = 10; // write other's static field, fail
b = A.a; // read other's static field, fail
}
}
class C {
public static int c;
static {
c = A.a; // read other's static field, fail
}
}
class G {
static G g;
static int i;
static {
g = new Gss(); // fail because recursive dependency
i = A.a; // read other's static field, fail
}
}
// Gs will be successfully initialized as G's status is initializing at that point, which will
// later aborted but Gs' transaction is already committed.
// Instantiation of Gs will fail because we try to invoke G's <init>
// but G's status will be StatusVerified. INVOKE_DIRECT will not initialize class.
class Gs extends G {} // fail because super class can't be initialized
class Gss extends Gs {}
// pruned because holding reference to non-image class
class ObjectRef {
static Class<?> klazz[] = new Class<?>[]{Add.class, Mul.class};
}
// non-image
class Add {
static int exec(int a, int b) {
return a + b;
}
}
// non-image
class Mul {
static int exec(int a, int b) {
return a * b;
}
}