因疫情關閉 倫敦最古老動物園求公眾捐贈物資

摘錄自2020年03月26日星島日報報導

英國因應疫情實施禁足令,世界最古老,有近200年歷史的倫敦動物園(London Zoo)也關閉,是自二戰以來首次,園方呼籲各界捐贈,以保護園內大約1.8萬隻動物。

有別於博物館或藝術館,倫敦動物園即使關閉,園內的動物仍有其需要,無論獅子、大猩猩、斑馬和長頸鹿等大型獸類,或是馬達加斯加蟑螂等其他大小動物。

倫敦動物學會營運長表示:「我們通常完全依賴公眾支撐開支,因此若沒有人造訪,就不會有收入。我們必須尋求其他收入來源,讓人們展現對我們的支持並進行捐贈。」她指出:「我們的動物吃得很多,我們必須確保供應鏈能夠繼續,且有高品質食物。無論是源自柯芬園的水果、蔬菜或肉類,我們需要持續的供應。」

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

※聚甘新

全球首例弱陽性寵物狗離世 傳飼主不願驗屍

摘錄自2020年3月18日自由時報報導

香港60歲女富豪周巧兒日前確診武漢肺炎,她的愛犬經檢測呈弱陽性反應,成為全球首隻低程度感染的寵物犬。港媒引述漁護署說法,表示狗狗已離世,且飼主不願驗屍確定死因。

綜合媒體報導,成為香港第85例的周巧兒在上月25日確診,隔天狗狗被送去檢疫,先後幾度採集樣本檢驗,結果「都是弱陽性」,反覆測試後直至本月12、13日,驗到2次陰性,漁護署14日將狗交還飼主。

報導指出,漁護署原本打算之後要再替狗狗安排抽血檢測,確認體內是否有抗體,未料狗狗於16日離世,據稱飼主表示「不願意」愛犬進行驗屍釐清死因。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司“嚨底家”!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※聚甘新

北極飆溫32度 瑞士警犬要穿鞋防燙傷

摘錄自2018年8月1日中央通訊社台北報導

極端熱浪與野火在全球釀災,連北極圈都出現32度高溫,德國河魚被熱死,瑞士警犬要穿鞋免遭燙傷。氣候科學家說,這就是氣候變遷真面目,全球暖化衝擊現正「即時上演」。

根據歐洲氣象網站severe-weather.eu,挪威的班納克(Banak)7月30日測得攝氏32度的氣溫,而挪威有些地方甚至測得更高的溫度。班納克已處北歐頂端,高於北極圈下緣350英里(560公里)。

美聯社報導,蹂躪大片歐洲的熱浪是造成奪命野火與農作受損的元兇,現在連淡水魚恐都要遭殃。德國部分地區飆到攝氏39度,熱到萊茵河與易北河內的魚群快窒息。漢堡(Hamburg)當地的有關單位在週末已從池塘撈起近1.1萬磅(約4.9公噸)的死魚。

瑞士蘇黎世的警犬已在腳掌上穿戴特殊的鞋,以免爪掌被火燙的街道灼傷。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※FB行銷專家,教你從零開始的技巧

※聚甘新

阿聯首座核電廠反應器獲發執照 阿拉伯世界新頁

摘錄自2020年2月17日中央社報導

阿拉伯聯合大公國今(17日)宣布,已向阿拉伯世界第一座核電廠「巴拉卡核電廠」的其中一座核子反應器核發營運執照,阿布達比王儲穆罕默德稱此舉為阿拉伯世界開啟「新頁」。

法新社報導,阿拉伯聯合大公國能源儲量豐富,但全國1000萬人口讓能源消耗量大,因此政府投入鉅資發展太陽能等替代能源。

阿布達比王儲穆罕默德(Sheikh Mohammed bin Zayed al-Nahyan)在推特上表示:「今天,隨著核發營運執照給第一座核電廠巴拉卡(Barakah),寫下我們發展和平核能的新頁。」

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※聚甘新

摧毀海洋、潟湖、飲用水的瘋狂計畫 土國總統仍要建伊斯坦堡運河

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※FB行銷專家,教你從零開始的技巧

※聚甘新

Azure AD B2C(二)使用Azure AD B2C為ASP.NET Core 應用設置社交帳戶(郵箱)登錄/註冊

20200624更新

sorry,上周剛換了電腦,開發工具還沒裝好,導致代碼遲遲沒有上傳!

————-我是分割線————

github:https://github.com/yunqian44/Azure.Active.DirectoryB2C.WebApp.git

一,引言

  上次關於Azure AD B2C 講到一些概念,有介紹到,Azure AD B2C 也是一種身份驗證的解決方案,但是它運行客戶使用其首選的社交,企業或者本地賬戶標識對應用程序和API進行單一登錄訪問。同樣,Azure AD B2C 使用基於標準的身份驗證協議,包括 OpenID Connect、OAuth 2.0 和 SAML。 它與大多數第三方的 idp 進行集成。今天,介紹如何使用 Azure Active Directory B2C (Azure AD B2C) 在 ASP.NET Web 應用程序中進行用戶登錄和註冊。 應用程序可以使用 Azure AD B2C 通過開放式標準協議對社交帳戶、企業帳戶和 Azure Active Directory 帳戶進行身份驗證。

二,正文

2.1,創建B2C租戶

  Azure Portal 左側菜單 點擊“創建資源”,同時搜索框中輸入 “ Azure Active Directory B2C”。

   點擊 “創建” 按鈕

  選擇 “創建新的 Azure Active AD B2C 租戶”

   輸入 “組織名稱”,”域名”,“區域”,“資源組”等名稱

  Organization name:CnBate B2C

  Initial domain name:cnbateb2c

 

  繼續選擇 ”Azure Active Directory B2C “,選擇 ”Link an existing Azure AD B2C to my Azure subscription“ 連接Azure AD B2C租戶到當前自己的訂閱 

   選擇剛剛註冊的 B2C 租戶,

  Resource group      :CnBate_RG      

  點擊 ”create“

   將Azure AD B2C 添加到左側菜單,在“所有服務” 搜索框中,搜索“Azure AD B2C” ,將鼠標懸停在搜索結果上,然後在工具提示中選擇星形圖標。 “Azure AD B2C”現在會显示在 Azure 門戶中的“收藏夾”下。

 

 

 2.2,註冊應用程序

  在門戶工具欄中選擇“目錄 + 訂閱”圖標,然後選擇包含 Azure AD B2C 租戶的目錄,切換成功后,在Azure Portal的左側菜單上選擇 ”Azure AD B2C“,在 Azure AD B2C 頁面選擇 ” 應用程序(舊版)“,點擊 ” 添加按鈕“

—————–敲黑板了———————-

(這裏先說一下,一定要選擇”應用程序(舊版)“,文章的最後會說明為什麼)

  輸入應用程序的名稱。 例如,“WebApp”;包含Web應用/Web API和運行隱式流,選擇 ”是“;回復URL,暫時先填寫 ”https://jwt.ms“,因為此時我們還沒有新建ASP.NET Core 的web應用,此地址是用來檢查令牌的,可以用來測試。(截圖裡面填寫的 ”http://localhost:9020/sign-oidc“ 是因為我之前運行demo,我自己本地的一個Web應用的地址,所以大家暫時忽略這個)

 

 2.3,創建用戶流 

  選擇 ”策略“-》”用戶流”,點擊 ”新建用戶流“

 

 

  在“建議”選項卡上選擇“註冊和登錄”用戶流。

 

  輸入該用戶流的名稱 ”B2C_1_signupsignin1“;標識提供者 勾選 ”郵件註冊“;用戶特性和聲明 收集特性和返回聲明勾選 ”姓“,”名“,”城市“,用戶特性和聲明勾選的選項意思是在註冊期間要從用戶收集併發送的聲明和屬性。 例如,“城市”和“姓”,”名“ 所對應的屬性和聲明。

 

   選擇運行流,選擇前面已註冊的名為 WebApp 的 Web 應用程序。

   此時,我們可以看到一個標準模板的登錄註冊的頁面,點擊 ”Sign up now“,進行註冊。

 

   輸入有效的电子郵件地址,單擊“發送驗證碼”,輸入收到的驗證碼,然後選擇“驗證代碼”。

   查看驗證碼,並且對驗證碼進行校驗,並且輸入相應的 ”姓“,”名“,”城市“,以及 ”登錄密碼“,點擊 ”Create“

 

 

 令牌將返回到 https://jwt.ms 並显示出來。

 2.4,創建ASP.NET Core Web 應用

 安裝:Microsoft.AspNetCore.Authentication.AzureADB2C.UI

  需要註冊驗證服務,這個地方默認的是 “AzureADB2C”,AddAzureADB2C方法綁定Azure AD B2C身份驗證終結點,回調地址,租戶所在的自定義域,客戶端Id,以及登錄/註冊,重置密碼,編輯信息的策略Id,其實也就是剛剛在B2C租戶中新建工作流的名稱。

   註冊Azure AD B2C 認證服務

services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
           .AddAzureADB2C(options=> {
               options.Instance = Appsettings.app("Azure_AD_B2C", "Instance");
               options.ClientId = Appsettings.app("Azure_AD_B2C", "ClientId");
               options.CallbackPath = Appsettings.app("Azure_AD_B2C", "CallbackPath");
               options.Domain = Appsettings.app("Azure_AD_B2C", "Domain");
               options.SignUpSignInPolicyId = Appsettings.app("Azure_AD_B2C", "SignUpSignInPolicyId");
               options.ResetPasswordPolicyId = Appsettings.app("Azure_AD_B2C", "ResetPasswordPolicyId");
               options.EditProfilePolicyId = Appsettings.app("Azure_AD_B2C", "EditProfilePolicyId");
           });

  開啟認證中間件服務

// open authentication middleware
app.UseAuthentication();

  appsettings.json的配置文件

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Azure_AD_B2C": {
    "Instance": "https://cnbateb2c.b2clogin.cn/tfp",
    "ClientId": "39280bbe-bfda-46b8-91c4-f96376f363d9",
    "CallbackPath": "/signin-oidc",
    "Domain": "cnbateb2c.partner.onmschina.cn",
    "SignUpSignInPolicyId": "B2C_1_signupsignin1",
    "ResetPasswordPolicyId": "",
    "EditProfilePolicyId": ""
  }
}
"Instance": "https://<your-tenant-name>.b2clogin.cn/tfp",
"ClientId": "<web-app-application-id>",
"Domain": "<your-b2c-domain>"
"CallbackPath": "/signin-oidc",
"SignUpSignInPolicyId": "B2C_1_test",
"ResetPasswordPolicyId": "",
"EditProfilePolicyId": ""

 

 

   HomeController=》about 方法加上 [Authorize] 

  修改項目啟動端口

 再回到 Azure Portal,為剛剛註冊的Azure AD B2C租戶裏面的WebApp應用設置新的回調地址 “http://localhost:9020/signin-oidc”

 

 

 

 

 

 

 

 

 大功告成!

三,問題匯總

問題1,B2C 應用註冊可以選擇 “應用註冊”,而不是“應用註冊舊版”嗎?

  不可以,Run user flow 中不能選擇 “應用註冊” 裏面的應用,目前在中國區B2C使用應用註冊(預覽)支持以下2種類型的account type, 這2種賬號類型是用於devops場景,因此,不應該使用user flow 來驗證這個類型的用戶。因此,Run user flow中不能選擇應用註冊(預覽)裏面的應用,這是by design的。

問題2,應用註冊的終結點為什麼當前註冊的B2C租戶的域不一致?例如下圖,一個是 com結尾,一個是 “cn”結尾

 答,這是azure 中國區的一個bug,我在4月份就反饋過類似的問題,之前他們是把終結點鏈接的域名後綴寫成com了,但是5月份他們更新的時候,應該沒有注意域名後面的當前租戶的鏈接地址

四,結尾

 今天的文章大概介紹了如果在我們的Web項目中集成Azure AD B2C,通過使用第三方的社交賬號 “郵箱”進行註冊,登陸。下一篇繼續介紹如何使用Azure AD B2C 保護的API資源。

代碼稍等,我會整理一下,上傳到github中

github:https://github.com/yunqian44/Azure.Active.DirectoryB2C.WebApp.git

作者:Allen 

版權:轉載請在文章明顯位置註明作者及出處。如發現錯誤,歡迎批評指正。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

使用IDEA+Gradle構建Spring5源碼並調試(手把手教程全圖解)

一、前言

  說一說我要寫這篇文章的初衷吧,前段時間有小夥伴在微信群求教怎樣構建spring源碼,他在網上找了n個教程跟着後面花了两天時間都沒構建好,正好我最近因工作原因從mac換成windows,開發環境要從零開始搭建和配置,想着也大概有一年多沒看過Spring源碼了,閱讀Spring源碼的好處我就不在此啰嗦了,我就藉此機會寫一篇構建Spring源碼的過程,希望能讓後面的朋友少走彎路,少踩坑。<br/>   開始之前,先說一下我的電腦是新的,也就是所有開發工具和環境都是最新下載和配置的,另外我沒使用梯&子走捷徑,也就是說本文的源碼構建速度是在正常使用網絡情況下,我自己達到的最佳速度,不代表任何人。本文使用到的開發工具及版本說明如下:

  • IntelliJ IDEA 2020.1
  • gradle-6.4.1
  • Spring-framework最新版(5.3.0-SNAPSHOT)

  現在,讓我們正式開始Spring源碼的構建之旅。

二、Spring源碼構建之旅

下載配置Gradle

  這個不是本文的重點又比較簡單,你得靠自己先去配置好,如果你實在不會,在文章後面留言,我下次專門給你們寫這個教程。

下載Spring源碼

1、在github上下載Spring最新版源碼,如下圖所示: 

2、下載完成以後解壓到你自己本地文件夾。 

  我知道因為不可描述原因,大家下載gradle和spring源碼可能比較耗時間,所以我把下載好的放在網盤了,需要的可以自己下載: Spring5源碼直通車 提取碼:srbm

修改配置

  重點來了,下載好源碼以後,我們要開始源碼構建了,在構建之前,我們先打開spring-framework-master,看我截圖的四個文件。下面來一一說明。 

 

1、import-into-idea.md:這是官方提供的spring源碼導入idea的步驟和注意說明,我已經翻譯過了,可以移步:IDEA導入Spring源碼調試必看

2、修改settings.gradle文件,下載依賴的網絡速度之不可描述原因,懂得人都懂,我們加上阿里雲的maven倉庫。

maven { url "https://maven.aliyun.com/repository/public" }

修改好之後如下圖所示:

3、修改gradle.properties文件,我都加了詳細註釋

version=5.3.0-SNAPSHOT
## 設置此參數主要是編譯下載包會佔用大量的內存,可能會內存溢出
org.gradle.jvmargs=-Xmx2048M
## 開啟 Gradle 緩存
org.gradle.caching=true
## 開啟并行編譯
org.gradle.parallel=true
## 啟用新的孵化模式
org.gradle.configureondemand=true
## 開啟守護進程 通過開啟守護進程,下一次構建的時候,將會連接這個守護進程進行構建,而不是重新fork一個gradle構建進程
org.gradle.daemon=true

  

修改好之後如下圖所示:

4、修改build.gradle文件,加上使用阿里雲倉庫,提高下載速度。

maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'}

  

修改好之後如下圖所示:

 

準備構建

1、再次為了證明我是從零開始的,我把gradle的倉庫依賴截圖給大家看,gradle的本地倉庫依賴位置是C:\Users\admin.gradle\caches\modules-2\files-2.1或者D:\work\tools\gradle\gradle-6.4.1\caches\modules-2\files-2.1,具體位置看你自己的設置。我的倉庫現在是空的,沒有任何下載好的依賴,截圖如下: 

2、預編譯spring-oxm,根據import-into-idea.md要求,我們需要先預編譯spring-oxm和spring-core,使用命令./gradlew :spring-oxm:compileTestJava,構建速度和截圖如下:

 

3、同上,預編譯spring-core,使用命令./gradlew :spring-core:compileTestJava,如下圖所示:    

至此,準備工作就完成的差不多了,接下來我們需要導入到IDEA,繼續往下看。<br><br><br>

 

IDEA導入Spring源碼

1、下面開始使用idea導入Spring源碼,File -> New -> Project from Existing Souces… 

2、選擇spring-framework-master項目

 

3、選擇使用gradle編譯,點擊finish。 

 

4、可以發現IDEA會自動開始構建編譯spring源碼。 

 

5、不要着急,還有最後一步,選擇File -> Settings -> Gradle,如下圖所示調整: 

 

6、去給對象問候一聲,或者去抽根煙(吸煙有害健康),或者遠處眺望一會,稍安勿躁,等回來時發現,不要網上說的一個小時、40分鐘、20分鐘,只要8m22s就完成Spring源碼的構建編譯工作,怎麼樣?還可以吧? 

補充,這是另一個小夥伴按照我的方法后構建速度,9m3s。    

到這兒,使用IDEA+Gradle構建Spring5源碼就已經全部完成。

三、驗證

  實踐是檢驗真理的唯一標準,那麼怎樣驗證我們上面的構建是否成功呢,很簡單,寫個demo測試一下就好了,下面進入驗證過程。

1、在spring-framework-master項目下新建我們自己的測試module,如下圖所示: 

2、選擇使用gradle

3、輸入自己的module名

4、既然要驗證,那我們肯定需要依賴spring的模塊,我們在我們剛剛新建的模塊下build.gradle文件中修改使用阿里雲倉庫,同時依賴spring-context模塊。

implementation(project(":spring-context"))

修改后如下如所示:

5、刷新依賴,重新編譯,速度同樣飛快。 

6、我們先寫一個配置類

package com.mazhichu.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName: MazhichuConfig
* @Description: 配置
* @Author: Moore
* @Date: 2020-06-08 12:30
* @Version: V1.0
*/
@Configuration
@ComponentScan("com.mazhichu")
public class MazhichuConfig {
}

7、寫一個實體Bean

package com.mazhichu.spring.repository;

import org.springframework.stereotype.Repository;
/**
* @ClassName: Hello
* @Description: bean
* @Author: Moore
* @Date: 2020-06-08 12:30
* @Version: V1.0
*/
@Repository
public class Hello {
	public void hello(){
		System.out.println("Hello,ma_zhichu!");
	}
}

  

8、編寫測試類,運行,如下圖所示: 

總結

至此,使用IDEA+Gradle構建Spring5源碼並簡單調試的教程就到這兒,本文所有內容都來自本人親自實踐,如果對你實實在在有幫助,點贊就是最大的鼓勵,如果你在構建過程中遇到任何問題,也歡迎留言告訴我,我看到後會第一時間幫你解答。如果你期待更好的文章,歡迎關注我的公眾號“碼之初”,謝謝!

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

Java內存溢出OutOfMemoryError的產生與排查

在java的虛擬機異常中,有兩個異常是大家比較關心的,一個是StackOverflowError,另一個是OutOfMemoryError。今天我們就來看看OutOfMemoryError是怎麼產生的,以及如何去排查這個異常。

概念

要了解什麼是OutOfMemoryError,我們可以直接看一下OutOfMemoryError的源碼,在類上的英文註釋很好的闡述了什麼是OutOfMemoryError,翻譯過來的意思是,由於內存不足,虛擬機沒有可分配的內存了,垃圾回收器也不能釋放更多的內存。在生產環境中,由於訪問量過大,把內存吃滿,會出現OutOfMemoryError的異常,小夥伴們如果沒有經驗的話,往往束手無策,到底是真的內存不夠用了,還是自己的程序有問題,也不知道如何去排查這樣的異常。

模擬OutOfMemoryError

在這裏,我們寫一段程序,來模擬一下OutOfMemoryError如何產生,我們創建一個List對象,然後向裡邊不停的添加1M的Byte,如下;

 public static void main(String[] args) {
     List<Byte[]> list = new ArrayList<>();
     int i = 0;
     try {
         while (true) {
             list.add(new Byte[1024 * 1024]);
             i++;
         }
     } catch (Throwable e) {
         e.printStackTrace();
         System.out.println("執行了"+i+"次");
     }
 }
  • 我們寫了一個while(true)循環,每次都add一個1M的字節對象,1024*1024正好1M。
  • 我們用i的值記錄總共執行了幾次。
  • 如果這樣不停的執行下去,不管你有多大的內存,都會被吃光的。

我們為了讓程序運行時,快速的拋出OutOfMemoryError異常,可以在java的啟動命令行增加啟動參數,設置堆內存的初始值和最大值。這兩個值在生產環境下,通常也是要配置的哦,要充分利用機器的內存嘛,如果不配置就會使用默認值。到時候由於內存不足向老闆申請機器,可別挨罵哦~

那這兩個參數怎麼去加呢?

  • -Xms ,-Xms設置初始堆內存的大小
  • -Xmx, -Xmx設置最大堆內存的大小

通常情況下,這兩個值設置成一樣就可以了,總之,我們設置了堆內存的大小。我們在IDEA的啟動配置中,統一設置堆內存為80M,如下;

好了~~我們運行一下,看看會不會拋出OutOfMemoryError異常吧

java.lang.OutOfMemoryError: Java heap space
	at com.diancan.JavaOOMDemo.main(JavaOOMDemo.java:14)
執行了14次

執行了14次,拋出了OutOfMemoryError異常。但是,如果拋出這樣一個異常,我們怎麼去排查呢?就這一行日誌也看不出什麼來啊。

排查

說到排查,如果我們能夠拿到異常時的內存快照,然後通過一些工具就可以了進行內存的分析了。那麼我們怎麼去拿到內存溢出時的快照呢?其實,JDK也為我們提供了這樣的命令參數,我們來看一下吧,

  • -XX:+HeapDumpOnOutOfMemoryError,從字面就可以很容易的理解,在發生OutOfMemoryError異常時,進行堆的Dump,這樣就可以獲取異常時的內存快照了。
  • -XX:HeapDumpPath=D:\heap-dump\ ,這個也很好理解,就是配置HeapDump的路徑,方便我們管理,這裏我們配置為D:\heap-dump,當然你也可以根據自己的需要,定義為其他的目錄。

注意,HeapDumpPath的目錄一定要手動創建好,如果沒有這個目錄,Dump會失敗的。

IDEA中的配置,如圖:

我們再運行一下程序,看看是什麼樣子,

java.lang.OutOfMemoryError: Java heap space
Dumping heap to D:\heap-dump\java_pid24312.hprof ...
Heap dump file created [123468648 bytes in 0.141 secs]
java.lang.OutOfMemoryError: Java heap space
	at com.diancan.JavaOOMDemo.main(JavaOOMDemo.java:14)
執行了14次

我們發現日誌上面多了點東西,創建了一個文件,在D:\heap-dump\java_pid24312.hprof。這個文件就是我們的內存快照。那麼問題來了,我們如何查看這個文件呢?直接打開是不行的,用寫字板等也是不行的,那怎麼辦?其實也沒那麼複雜,使用JDK自帶的jvisualvm就可以查看。

這裏邊有個小坑,如果大家用JDK8,可以在JDK的bin目錄下找到jvisualvm.exe,但是如果你使用的是JDK8以上的版本,就本示例中,使用的是JDK11,在bin目錄下是找不到jvisualvm.exe的。大家可以去visualvm的主頁下載。

我們啟動visualvm,進入到如下的頁面,

然後,點擊左上角的加載快照按鈕,然後選擇剛才我們Dump的文件,

我們重點看一下右側中間的部分,

類的實例大小排序,可以看到,我們的Byte佔了96.5%。詳細的信息,我們可以點進去看,包括變量里存的內容,這樣我們就可以很快的定位到內存溢出的位置,並且可以判斷是真的內存不夠了,還是我們的代碼出了問題。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※回頭車貨運收費標準

[cpp]C++中的析構函數

C++中的析構函數

簡介

析構函數(Destructors),是對象的成員函數,沒有返回值也沒有參數,且一個類只有一個析構函數,當對象被銷毀的時候調用,被銷毀通常有這麼幾個情況。

  • 函數執行結束
  • 程序執行結束
  • 程序塊包含的局部變量
  • delete操作

什麼時候要自己寫析構函數?

編譯器會自動創建默認的析構函數,通常都沒有問題,但是當我們在類中動態分配了內存空間時,我們需要手段的回收這塊空間,防止內存溢出。就像這樣

class String 
{ 
private: 
	char *s; 
	int size; 
public: 
	String(char *); // constructor 
	~String();	 // destructor 
}; 
 
String::String(char *c) 
{ 
	size = strlen(c); 
	s = new char[size+1]; 
	strcpy(s,c); 
} 
 
String::~String() 
{ 
	delete []s; 
} 

私有的析構函數

可以將析構函數的訪問權限設置為private,設置時沒有問題的,但是一個問題就是,通常的手段就沒法調用析構函數了。

如下所示,程序結束后要調用析構函數,但是析構函數時私有的沒法調用,所以會編譯出錯。

#include <iostream> 
using namespace std; 
class Test { 
private: 
	~Test() {} 
}; 
int main() 
{ 
	Test t; 
} 

以下這樣不會有問題,因為沒有對象被建立,也不用析構

int main() 
{ 
    Test* t;                                          
} 

以下這樣也不會有問題,因為動態分配的內存需要程序員手段釋放,所以程序結束時沒有釋放內存,也沒有調用析構函數。這裏插一句,動態分配的內存如果不手動釋放,程序結束后也會不會釋放,但是現代操作系統可以幫我們釋放,因為這個動態分配的內存和這個進程有關,操作系統應該可以捕獲到這個泄露的內存從而釋放。(查資料看到的)

int main() 
{ 
    Test* t = new Test; 
} 

如果使用delete來刪除對象,會編譯出錯

int main() 
{ 
    Test* t = new Test;
    delete t;//編譯出錯,無法調用私有的析構函數 
}

可以利用Friend函數,進行對象的銷毀,因為Friend可以訪問私有成員,所以可以訪問析構函數。


#include <iostream> 

class Test { 
private: 
	~Test() {} 
	friend void destructTest(Test*); 
}; 

void destructTest(Test* ptr) 
{ 
	delete ptr; 
} 

int main() 
{ 
	Test* ptr = new Test; 
	destructTest(ptr); 

	return 0; 
} 

或者給類寫一個銷毀的方法,在需要銷毀的時候調用。

class Test { 
public:
    destroy(){delete this};
private: 
	~Test() {} 
};

那麼什麼時候需要使用私有的析構函數呢?當我們只希望動態分配對象空間(在堆上)時候,用私有析構,就防止了在棧上分配,因為在編譯階段就會出錯。

虛析構函數

當類用到多態的特性時候,使用虛析構函數。看如下的例子。

#include <iostream>
using namespace std;
class Base
{
public:
    Base(){
        cout << "Base Constructor Called\n";
    }
    ~Base(){
        cout << "Base Destructor called\n";
    }
};
class Derived1: public Base
{
public:
    Derived1(){
        cout << "Derived constructor called\n";
    }
    ~Derived1(){
        cout << "Derived destructor called\n";
    }
};
int main()
{
    Base *b = new Derived1();
    delete b;
}

例子里的析構函數都不是虛函數,當我們想用基類的指針來刪除派生類對象的時候,就出現了問題,“undefined behavior”,c++標準里規定,只由編譯器實現,通常這時不會報錯,會調用基類的析構函數。但這應該不是我們想要的,這會導致內存泄漏。所以要把析構函數置為虛函數。(msvc似乎不用給析構函數加virtual,默認就是虛的,gcc沒有默認還是要加的)

另外虛析構函數可以是純虛析構函數,但是要提供函數體,不然沒法析構,因為虛析構函數和一般的虛函數的overide還不一樣,虛析構函數要挨個執行,不提供函數體,會編譯出錯。

析構函數執行的順序

派生類,成員對象,基類這樣

class B
{public: virtual ~B(){cout<<"基類B執行了"<<endl; }
};

class D
{public:virtual ~D(){cout<<"成員D執行了"<<endl; }
} ;

class E
{public:virtual ~E(){cout<<"成員E執行了"<<endl; }
} ;

class A
{public:virtual ~A(){cout<<"基類A執行了"<<endl;}; 
};

class C:public A,B
{
    public:virtual ~C(){cout<<"派生類執行了"<<endl;};
    private:
        E e;
        D d;
};

int main()  
{  
    C *c;
    c=new C();
    delete c;
}   

結果為:

  • 派生類執行了
  • 成員D執行了
  • 成員E執行了
  • 基類B執行了
  • 基類A執行了

參考

  • [1]什麼時候使用虛函數https://stackoverflow.com/questions/461203/when-to-use-virtual-destructors
  • [2]析構函數https://www.geeksforgeeks.org/destructors-c/
  • [3]虛析構函數https://www.geeksforgeeks.org/virtual-destructor/
  • [4]純析構函數https://www.geeksforgeeks.org/pure-virtual-destructor-c/

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

Oracle調用Java方法(上)如何使用LoadJava命令和如何將簡單的Jar包封裝成Oracle方法

最近在工作中遇到了遇到了一個需求需要將TIPTOP中的數據導出成XML並上傳到FTP主機中,但是4GL這方面的文檔比較少最終決定使用Oracle調用Java的方法,在使用的過程中發現有很多的坑,大部分的博客只粗略的介紹了下導致耗費了很多時間,在這裏分兩個博文詳細的記錄一下這個功能,填一下坑,希望可以幫助到大家。

首先 每個Oracle版本對應的OJVM的版本是不一樣的我的Oracle 版本是 Database 11g Release 2 對應的是jdk1.6 所以寫Java代碼的時候要注意版本號,其次這個功能是默認關閉的所以需要先安裝OJVM,腳本安裝語法如下(使用sys用戶登陸sqlplus安裝):

安裝JVM運行環境

@?/javavm/install/initjvm.sql

卸載JVM運行環境

@?/javavm/install/rmjvm.sql

查詢OJVM是否安裝成功

SELECT * FROM DBA_REGISTRY WHERE COMP_ID = 'JAVAVM';

執行腳本時間比較長要耐心等待一會,安裝完成后需要根據Java文件類型來選擇導入語句
LoadJava參數有

  • -u(用於輸入用戶名及密碼)
  • -v(用於輸出詳細的反饋信息)
  • -resolve(對於沒有編譯的Java文件可以用resolve來編譯)
  • -f(不管之前是否已經導入過該Java類,都強制再次導入)

當導入Class文件時,可以用如下命令:

loadjava –u username/userpassword –v filename.class

當刪除Class文件時,可以用如下命令:

dropjava –u username/userpassword –v filename.class

當導入Java文件時,可以用如下命令:

loadjava –u username/userpassword –v -resolve filename.java

當刪除Java文件時,可以用如下命令:

dropjava –u username/userpassword –v filename.java

當導入jar文件時,可以用如下命令:

loadjava –u username/userpassword –v -resolve filename.jar

當刪除jar文件時,可以用如下命令:

dropjava –u username/userpassword –v -resolve filename.jar

如果是比較簡單的Java方法可以直接使用PL/SQL進行編寫,需要調用的方法必須是public static 修飾的(Java方法若需要用到其他價包,報ORA-29521找不到類的錯 將在下一個博客中說到)

create or replace and compile java source named JavaName as [Java代碼]

當使用這種方法的時候可以在PL/SQL 左邊的Java Sources 文件夾中找得到源碼並編輯,如果導入的是.Java或.Jar格式的就只能在Java Classes 文件夾中找得到並且不能用PL/SQL編輯.

如果導入正常的話使用下面的語句可以查詢當前用戶已經導入的Java類,查詢出來的狀態必須是”VALID”,否則Oracle則不能調用必須解決報錯信息重新導入才能調用

SELECT OBJECT_ID, OBJECT_NAME, OBJECT_TYPE, STATUS
FROM USER_OBJECTS
WHERE OBJECT_TYPE LIKE 'JAVA%'

以上代碼都執行完成后就可以將Java代碼封裝成成Oracle 方法(function) ,存儲過程(Procedures) 這2個主要是返回值的區別 如果有返回值可以封裝成function ,沒有返回值可以封裝成Procedures,如果有多個返回值…emmmm Java沒有多個返回值=。= 我需要封裝成function則封裝的語句如下:

CREATE OR REPLACE FUNCTION FunctionName(str1  NVARCHAR2,
  str2   NVARCHAR2,
  str3   NVARCHAR2,
  str4  NVARCHAR2,
  str5   NVARCHAR2)
  RETURN NVARCHAR2 AS
  LANGUAGE JAVA NAME 'com/xxx/xxx/xxx/xxx.ClassName(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String) return java.lang.String';

這個語句需要注意2點其一就是Java方法的包名需要用“/”而分割類名用“.” 這個當時卡了很久算是一個坑,其二Java方法的傳入類型要和數據庫類型相對應例如: NVARCHAR2和String ,更詳細的對應關係可以看Oracle 官方的文檔

那如果需要傳入的是一大堆表數據呢? 其實這種類型對應並不支持複雜的類型,要想獲得複雜數據 需要在Jar包中加入JDBC包使用JDBC來建立查詢語句來獲取數據 獲取JDBC的Connection對象的時候可以可以這樣寫,不用寫數據庫鏈接名和賬號密碼,可以直接使用數據庫的連接。
Connection conn = DriverManager.getConnection(“jdbc:default:connection:”);

詳情也可以參照Oracle官方文檔中的這一單元:Using the Server-Side Internal JDBC Driver

本文主要介紹了如何導入和如何封裝Java方法,如果你的業務邏輯比較複雜需要用到第三方jar包來實現自己的業務邏輯,或者發生了ORA-29521: referenced name java/xxx/xxx/xxx could not be found錯誤那麼這些問題將在下一篇中說到。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※網頁設計最專業,超強功能平台可客製化