Android 源码中ZygoteInit 调用ActivityThread main 函数 实例

本文讲通过java main函数调用 其它main函数执行 (当然也可以调用其它函数) ;android 部分源码

被调用的 java main函数

package main;

public class Main {

public static void main(String[] args) {

System.out.println(args[0]);

}

}

 

调用Java main函数的类

package main;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class TestMain {
    public static void main(String[] args) {
        TestMain testMain = new TestMain();

        Runnable runnable = findStaticMain("main.Main", new String[] { "testtest" }, testMain.getClass().getClassLoader());
        runnable.run();
    }

    /**
     * Invokes a static "main(argv[]) method on class "className". Converts various
     * failing exceptions into RuntimeExceptions, with the assumption that they will
     * then cause the VM instance to exit.
     *
     * @param className
     *            Fully-qualified class name
     * @param argv
     *            Argument vector for main()
     * @param classLoader
     *            the classLoader to load {@className} with
     */
    protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
        Class<?> cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException("Missing class when invoking static main " + className, ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException("Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException("Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (!(Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException("Main method is not public and static on " + className);
        }

        /*
         * This throw gets caught in ZygoteInit.main(), which responds by invoking the
         * exception's run() method. This arrangement clears up all the stack frames
         * that were required in setting up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }
}
 

利用反射调用main函数

package main;

 

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

 

/**

 * Helper class which holds a method and arguments and can call them. This is

 * used as part of a trampoline to get rid of the initial process setup stack

 * frames.

 */

public class MethodAndArgsCaller implements Runnable {

/** method to call */

private final Method mMethod;

 

/** argument array */

private final String[] mArgs;

 

public MethodAndArgsCaller(Method method, String[] args) {

mMethod = method;

mArgs = args;

}

 

public void run() {

try {

mMethod.invoke(null, new Object[] { mArgs });

} catch (IllegalAccessException ex) {

throw new RuntimeException(ex);

} catch (InvocationTargetException ex) {

Throwable cause = ex.getCause();

if (cause instanceof RuntimeException) {

throw (RuntimeException) cause;

} else if (cause instanceof Error) {

throw (Error) cause;

}

throw new RuntimeException(ex);

}

}

}

这个报错是什么原因 08-25 13:55:17.847685 10355 10355 E AndroidRuntime: FATAL EXCEPTION: main Process: com.android.systemui:tuner, PID: 10355 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.systemui/com.android.systemui.tuner.TunerActivity}: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.android.systemui.tuner.TunerFragment: could not find Fragment constructor at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4624) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4821) at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:7159) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:7010) at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:106) at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:63) at android.app.servertransaction.TransactionExecutor.executeNonLifecycleItem(TransactionExecutor.java:138) at android.app.servertransaction.TransactionExecutor.executeTransactionItems(TransactionExecutor.java:108) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:85) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:3110) at android.os.Handler.dispatchMessage(Handler.java:115) at android.os.Looper.loopOnce(Looper.java:298) at android.os.Looper.loop(Looper.java:408) at android.app.ActivityThread.main(ActivityThread.java:9952) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:613) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1074) Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.android.systemui.tuner.TunerFragment: could not find Fragment constructor at android.app.Fragment.instantiate(Fragment.java:567) at android.app.FragmentContainer.instantiate(FragmentContainer.java:53) at android.app.FragmentState.instantiate(FragmentState.java:77) at android.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:2867) at android.app.FragmentController.restoreAllState(FragmentController.java:143) at android.app.Activity.onCreate(Activity.java:1924) at com.android.systemui.tuner.TunerActivity.onCreate(go/retraceme aff8b06f686a392573423f635cd3b1b8cadac5d31fb1f98ab46c18e784738f44:1) at android.app.Activity.performCreate(Activity.java:9391) at android.app.Activity.performCreate(Activity.java:9363) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1541) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:4598) ... 16 more Caused by: java.lang.NoSuchMethodException: com.android.systemui.tuner.TunerFragment.<init> [] at java.lang.Class.getConstructor0(Class.java:3385) at java.lang.Class.getConstructor(Class.java:2477) at android.app.Fragment.instantiate(Fragment.java:548) ... 26 more
最新发布
08-31
<think> 我们正在分析一个特定的Android系统错误,该错误发生在SystemUI组件的TunerActivity启动时。 错误信息:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.systemui/com.android.systemui.tuner.TunerActivity}: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.android.systemui.tuner.TunerFragment: could not find Fragment constructor 根据错误堆栈,问题在于实例化TunerFragment时找不到Fragment的构造函数。这通常是因为Fragment没有提供无参数的构造函数。 在Android中,当系统需要重新创建Fragment(例如在配置更改后)时,它会使用无参数的构造函数实例化Fragment。因此,每个Fragment都必须有一个公共的无参数构造函数。 可能的原因: 1. TunerFragment类没有定义无参数的构造函数。 2. TunerFragment类中定义了带参数的构造函数,但没有同时提供无参数的构造函数。 解决方案: 检查TunerFragment类,确保有一个公共的无参数构造函数。如果已经定义了其他构造函数,必须显式添加一个无参数构造函数。 例如: 错误情况: public class TunerFragment extends Fragment { public TunerFragment(int someParam) { // 带参数的构造函数 } } 正确修改: public class TunerFragment extends Fragment { public TunerFragment() { // 无参数构造函数必须存在 } public TunerFragment(int someParam) { // 带参数的构造函数(可选,但无参数的必须提供) } } 另外,注意:在Fragment中,避免在构造函数中传递参数。如果需要传递参数,应该使用`setArguments(Bundle bundle)`方式。 因为在重新创建Fragment时,系统会调用无参数的构造函数,然后通过`setArguments`来恢复之前的状态。所以,在Fragment中,参数应该通过Bundle来传递。 例如: public class TunerFragment extends Fragment { public static TunerFragment newInstance(int someParam) { TunerFragment fragment = new TunerFragment(); Bundle args = new Bundle(); args.putInt("someParam", someParam); fragment.setArguments(args); return fragment; } public TunerFragment() { // 必须有无参构造函数 } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { int someParam = getArguments().getInt("someParam"); // 使用参数 } } } 因此,针对SystemUI中的TunerFragment,我们需要检查其构造函数。由于这是系统代码,可能的问题是在定制系统时修改了该Fragment,或者系统在升级过程中出现了兼容性问题。 对于普通开发者,如果遇到类似问题,应检查自定义的Fragment类。但对于系统级错误,可能需要检查系统源码或等待系统更新修复。 注意:错误信息中明确指出了“could not find Fragment constructor”,所以基本可以确定是构造函数的问题。 另外,我们参考了之前的一些引用,但那些引用主要针对的是普通应用开发中的空指针或布局文件错误,而当前错误是系统组件中的Fragment实例化问题,所以原因不同。 总结:该错误的原因是TunerFragment缺少无参数的构造函数,导致系统在实例化Fragment时失败。 </think> 根据提供的错误信息和分析,`java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.systemui/com.android.systemui.tuner.TunerActivity}: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.android.systemui.tuner.TunerFragment: could not find Fragment constructor` 报错的核心原因是: ### 主要原因 1. **Fragment构造函数缺失** `TunerFragment` 缺少**公共的无参构造函数**。Android系统在重建Fragment时(如屏幕旋转、内存回收后恢复),必须通过无参构造函数实例化Fragment。当系统找不到无参构造函数时,会抛出`Fragment$InstantiationException`异常。 2. **自定义构造函数未正确处理**(常见情况) 如果`TunerFragment`只定义了带参数的构造函数(如`TunerFragment(int param)`),但未同时声明无参构造函数,系统无法通过反射创建实例。典型的错误代码结构: ```java public class TunerFragment extends Fragment { // 错误:只有带参构造,缺少无参构造 public TunerFragment(int config) { ... } } ``` --- ### 解决方案 1. **添加无参构造函数** 在`TunerFragment`类中显式声明公共无参构造函数: ```java public class TunerFragment extends Fragment { // 必须添加的公共无参构造 public TunerFragment() {} // 原有带参构造(可选保留) public TunerFragment(int config) { ... } } ``` 2. **使用`setArguments()`传递参数** **禁止通过构造函数传参**!应采用Bundle传递数据: ```java // 创建Fragment的正确方式 public static TunerFragment newInstance(int config) { TunerFragment fragment = new TunerFragment(); // 调用无参构造 Bundle args = new Bundle(); args.putInt("CONFIG_KEY", config); fragment.setArguments(args); return fragment; } // 在Fragment中读取参数 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { int config = getArguments().getInt("CONFIG_KEY"); } } ``` 3. **检查ProGuard混淆规则**(系统级) 如果是系统定制ROM,需确认ProGuard未移除无参构造: ```proguard -keepclassmembers class * extends android.app.Fragment { public <init>(); } ``` --- ### 根本原因分析 此错误属于Android框架的**固有机制限制**: - Fragment的生命周期由系统管理,重建时**强制调用无参构造函数** - 任何自定义构造函数都会破坏系统恢复机制 - 常见于系统UI定制开发(如SystemUI模块),尤其在Android 4.0+后Fragment管理更严格[^1][^3] 此类问题在系统级开发中的出现频率远高于普通应用,因涉及框架层与自定义组件的交互约束。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值