نسخه های جاوا در بیلدهای اندروید

چه کد منبع شما به زبان جاوا، کاتلین یا هر دو نوشته شده باشد، مکان‌های مختلفی وجود دارد که باید یک نسخه زبان JDK یا جاوا را برای ساخت خود انتخاب کنید.

مروری بر روابط JDK در ساخت Gradle
شکل 1. روابط JDK در یک ساخت

واژه نامه

کیت توسعه جاوا (JDK)
کیت توسعه جاوا (JDK) شامل:
  • ابزارهایی مانند کامپایلر، نمایه ساز و ایجاد کننده آرشیو. اینها در پشت صحنه در طول ساخت شما برای ایجاد برنامه شما استفاده می شوند.
  • کتابخانه‌هایی حاوی APIهایی که می‌توانید از کد منبع Kotlin یا Java خود تماس بگیرید. توجه داشته باشید که همه عملکردها در اندروید در دسترس نیستند.
  • ماشین مجازی جاوا (JVM)، مفسری که برنامه های جاوا را اجرا می کند. شما از JVM برای اجرای Android Studio IDE و ابزار ساخت Gradle استفاده می کنید. JVM در دستگاه های اندرویدی یا شبیه سازها استفاده نمی شود.
JetBrains Runtime (JBR)
JetBrains Runtime (JBR) یک JDK پیشرفته است که با Android Studio توزیع شده است. این شامل چندین بهینه سازی برای استفاده در استودیو و محصولات JetBrains مرتبط است، اما می تواند برای اجرای سایر برنامه های جاوا نیز استفاده شود.

چگونه یک JDK را برای اجرای Android Studio انتخاب کنم؟

توصیه می کنیم برای اجرای اندروید استودیو از JBR استفاده کنید. این برنامه برای آزمایش Android Studio مستقر شده و از آن استفاده می شود و شامل پیشرفت هایی برای استفاده بهینه از Android Studio است. برای اطمینان از این موضوع، متغیر محیطی STUDIO_JDK را تنظیم نکنید.

اسکریپت های راه اندازی اندروید استودیو به ترتیب زیر به دنبال JVM می گردند:

  1. متغیر محیطی STUDIO_JDK
  2. پوشه studio.jdk (در توزیع Android Studio)
  3. دایرکتوری jbr (JetBrains Runtime)، در توزیع Android Studio. توصیه می شود.
  4. متغیر محیطی JDK_HOME
  5. متغیر محیطی JAVA_HOME
  6. java قابل اجرا در متغیر محیطی PATH

چگونه انتخاب کنم که کدام JDK بیلدهای Gradle من را اجرا کند؟

اگر Gradle را با استفاده از دکمه‌های Android Studio اجرا می‌کنید، مجموعه JDK در تنظیمات Android Studio برای اجرای Gradle استفاده می‌شود. اگر Gradle را در یک ترمینال اجرا کنید، چه در داخل یا خارج از Android Studio، متغیر محیطی JAVA_HOME (در صورت تنظیم) تعیین می کند که کدام JDK اسکریپت های Gradle را اجرا می کند. اگر JAVA_HOME تنظیم نشده باشد، از دستور java در متغیر محیطی PATH شما استفاده می کند.

برای ثابت‌ترین نتایج، مطمئن شوید که متغیر محیطی JAVA_HOME و پیکربندی Gradle JDK را در Android Studio روی همان JDK تنظیم کرده‌اید.

هنگام اجرای بیلد، Gradle فرآیندی به نام Daemon را برای اجرای ساخت واقعی ایجاد می کند. تا زمانی که بیلدها از همان نسخه JDK و Gradle استفاده می کنند، می توان از این فرآیند دوباره استفاده کرد. استفاده مجدد از دیمون زمان شروع یک JVM جدید و مقداردهی اولیه سیستم ساخت را کاهش می دهد.

اگر ساخت‌ها را با نسخه‌های JDK یا Gradle مختلف شروع کنید، دیمون‌های اضافی ایجاد می‌شوند که CPU و حافظه بیشتری مصرف می‌کنند.

پیکربندی Gradle JDK در Android Studio

برای تغییر پیکربندی Gradle JDK پروژه موجود، تنظیمات Gradle را از File (یا Android Studio در macOS) > Settings > Build, Execution, Deployment > Build Tools > Gradle باز کنید. کشویی Gradle JDK شامل گزینه های زیر برای انتخاب است:

  • ماکروهایی مانند JAVA_HOME و GRADLE_LOCAL_JAVA_HOME
  • ورودی های جدول JDK با فرمت vendor-version مانند jbr-17 که در فایل های پیکربندی اندروید ذخیره می شوند.
  • دانلود JDK
  • اضافه کردن یک JDK خاص
  • JDKهای محلی شناسایی شده از دایرکتوری نصب پیش فرض JDK سیستم عامل

گزینه انتخاب شده در گزینه gradleJvm در فایل .idea/gradle.xml پروژه ذخیره می شود و وضوح مسیر JDK آن برای اجرای Gradle هنگام شروع از طریق Android Studio استفاده می شود.

شکل 2. تنظیمات JDK را در Android Studio انجام دهید.

ماکروها انتخاب مسیر پروژه پویا JDK را فعال می کنند:

  • JAVA_HOME : از متغیر محیطی با همین نام استفاده می کند
  • GRADLE_LOCAL_JAVA_HOME : از ویژگی java.home در فایل .gradle/config.properties استفاده می کند که به طور پیش فرض روی JetBrains Runtime است.

JDK انتخاب شده برای اجرای ساخت Gradle شما و حل و فصل مراجع JDK API هنگام ویرایش اسکریپت های ساخت و کد منبع شما استفاده می شود. توجه داشته باشید که compileSdk مشخص شده بیشتر محدود می کند که کدام نمادهای جاوا هنگام ویرایش و ساخت کد منبع شما در دسترس باشد.

مطمئن شوید که نسخه JDK را انتخاب کنید که بالاتر یا برابر با نسخه های JDK مورد استفاده پلاگین هایی است که در ساخت Gradle خود استفاده می کنید. برای تعیین حداقل نسخه JDK مورد نیاز برای Android Gradle Plugin (AGP)، جدول سازگاری را در یادداشت‌های انتشار ببینید.

به عنوان مثال، پلاگین Android Gradle نسخه 8.x به JDK 17 نیاز دارد. اگر می‌خواهید یک بیلد Gradle را اجرا کنید که از آن با نسخه قبلی JDK استفاده می‌کند، پیامی مانند:

An exception occurred applying plugin request [id: 'com.android.application']
> Failed to apply plugin 'com.android.internal.application'.
   > Android Gradle plugin requires Java 17 to run. You are currently using Java 11.
      Your current JDK is located in /usr/local/buildtools/java/jdk
      You can try some of the following options:
       - changing the IDE settings.
       - changing the JAVA_HOME environment variable.
       - changing `org.gradle.java.home` in `gradle.properties`.

کدام API های جاوا را می توانم در کد منبع جاوا یا کاتلین خود استفاده کنم؟

یک برنامه اندروید می تواند از برخی از API های تعریف شده در JDK استفاده کند، اما نه از همه آنها. Android SDK پیاده سازی بسیاری از توابع کتابخانه جاوا را به عنوان بخشی از API های موجود خود تعریف می کند. ویژگی compileSdk مشخص می کند که از کدام نسخه Android SDK هنگام کامپایل کد منبع Kotlin یا Java خود استفاده کنید.

کاتلین

android {
    ...
    compileSdk = 33
}

شیار

android {
    ...
    compileSdk 33
}

هر نسخه از اندروید از نسخه خاصی از JDK و زیر مجموعه ای از API های جاوای موجود خود پشتیبانی می کند. اگر از یک Java API موجود در compileSdk استفاده می‌کنید که در minSdk مشخص‌شده موجود نیست، ممکن است بتوانید از API در نسخه قبلی Android از طریق فرآیندی به نام desugaring استفاده کنید. به Java 11+ APIهای موجود از طریق desugaring برای APIهای پشتیبانی شده مراجعه کنید.

از این جدول برای تعیین اینکه کدام نسخه جاوا توسط هر API Android پشتیبانی می‌شود و کجا می‌توانید جزئیات مربوط به کدام APIهای جاوا را پیدا کنید، استفاده کنید.

اندروید جاوا API و ویژگی های زبان پشتیبانی می شود
14 (API 34) 17 کتابخانه های اصلی
13 (API 33) 11 کتابخانه های اصلی
12 (API 32) 11 Java API
11 و پایین تر نسخه های اندروید

کدام JDK کد منبع جاوا من را کامپایل می کند؟

زنجیره ابزار جاوا JDK حاوی کامپایلر جاوا است که برای کامپایل هر کد منبع جاوا استفاده می شود. این JDK همچنین تست های javadoc و unit را در طول ساخت اجرا می کند.

پیش فرض زنجیره ابزار بر روی JDK مورد استفاده برای اجرای Gradle است. اگر از پیش‌فرض استفاده می‌کنید و یک بیلد را روی ماشین‌های مختلف اجرا می‌کنید (به عنوان مثال، ماشین محلی شما و یک سرور Continuous Integration جداگانه)، در صورت استفاده از نسخه‌های مختلف JDK، نتایج ساخت شما می‌تواند متفاوت باشد.

برای ایجاد یک بیلد سازگارتر، می توانید به صراحت یک نسخه زنجیره ابزار جاوا را مشخص کنید. با مشخص کردن این:

  • یک JDK سازگار را روی سیستمی که بیلد را اجرا می کند، تعیین می کند.
    • اگر JDK سازگاری وجود نداشته باشد (و یک ابزار Resolver تعریف شده باشد)، یکی را دانلود می کند.
  • APIهای زنجیره ابزار جاوا را برای تماس از کد منبع در معرض دید قرار می دهد.
  • منبع جاوا را با استفاده از نسخه زبان جاوا آن کامپایل می کند.
  • پیش فرض های sourceCompatibility و targetCompatibility را فراهم می کند.

توصیه می کنیم همیشه زنجیره ابزار جاوا را مشخص کنید و یا مطمئن شوید که JDK مشخص شده نصب شده است یا یک حل کننده زنجیره ابزار به بیلد خود اضافه کنید.

می توانید زنجیره ابزار را مشخص کنید که آیا کد منبع شما به زبان جاوا، کاتلین یا هر دو نوشته شده است. زنجیره ابزار را در سطح بالای فایل build.gradle(.kts) ماژول خود مشخص کنید.

نسخه ابزار جاوا را به صورت زیر مشخص کنید:

کاتلین

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

شیار

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

اگر منبع شما Kotlin، Java یا ترکیبی از هر دو باشد، این کار را انجام می دهد.

نسخه JDK زنجیره ابزار می تواند مانند JDK مورد استفاده برای اجرای Gradle باشد، اما به خاطر داشته باشید که آنها اهداف مختلفی را دنبال می کنند.

از کدام ویژگی های منبع زبان جاوا می توانم در کد منبع جاوا استفاده کنم؟

ویژگی sourceCompatibility تعیین می کند که کدام ویژگی های زبان جاوا در طول کامپایل منبع جاوا در دسترس هستند. این بر منبع کاتلین تأثیر نمی گذارد.

sourceCompatibility در فایل build.gradle(.kts) ماژول به صورت زیر مشخص کنید:

کاتلین

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
    }
}

شیار

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
    }
}

اگر مشخص نشده باشد، این ویژگی به طور پیش‌فرض روی نسخه جاوا ابزار است. اگر از زنجیره ابزار جاوا استفاده نمی‌کنید، به طور پیش‌فرض به نسخه‌ای انتخاب می‌شود که توسط افزونه Android Gradle انتخاب شده است (مثلاً جاوا 8 یا بالاتر).

هنگام کامپایل منبع Kotlin یا Java از کدام ویژگی های باینری جاوا می توان استفاده کرد؟

ویژگی‌های targetCompatibility و jvmTarget به ترتیب نسخه‌ی فرمت کلاس جاوا را تعیین می‌کنند که هنگام تولید بایت کد برای منبع جاوا و کاتلین کامپایل‌شده استفاده می‌شود.

برخی از ویژگی های Kotlin قبل از اضافه شدن ویژگی های معادل جاوا وجود داشتند. کامپایلرهای اولیه کاتلین باید راه خود را برای نمایش آن ویژگی های کاتلین ایجاد می کردند. برخی از این ویژگی ها بعداً به جاوا اضافه شدند. با سطوح بعدی jvmTarget ، کامپایلر Kotlin ممکن است مستقیماً از ویژگی جاوا استفاده کند که ممکن است منجر به عملکرد بهتر شود.

نسخه های مختلف اندروید از نسخه های مختلف جاوا پشتیبانی می کنند. می‌توانید با افزایش targetCompatibility و jvmTarget از ویژگی‌های اضافی جاوا استفاده کنید، اما ممکن است مجبور شوید حداقل نسخه Android SDK خود را نیز افزایش دهید تا از در دسترس بودن این ویژگی اطمینان حاصل کنید.

توجه داشته باشید که targetCompatibility باید بزرگتر یا مساوی با sourceCompatibility باشد. در عمل، sourceCompatibility ، targetCompatibility و jvmTarget معمولاً باید از یک مقدار استفاده کنند. می توانید آنها را به صورت زیر تنظیم کنید:

کاتلین

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget = "17"
    }
}

شیار

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions {
        jvmTarget '17'
    }
}

اگر مشخص نشده باشد، این ویژگی‌ها به طور پیش‌فرض به نسخه Java toolchain می‌رسند. اگر از زنجیره ابزار جاوا استفاده نمی کنید، ممکن است مقادیر پیش فرض متفاوت باشد و باعث ایجاد مشکلاتی در ساخت شود. بنابراین، توصیه می کنیم همیشه این مقادیر را به صراحت مشخص کنید یا از زنجیره ابزار جاوا استفاده کنید.